/**
   @file sys_usw_l2_fdb.c

   @date 2013-6-13

   @version v2.0

   The file implement   FDB/L2 unicast /mac filtering /mac security/L2 mcast functions
 */

#include "sal.h"
#include "ctc_const.h"
#include "ctc_hash.h"
#include "ctc_vector.h"
#include "ctc_linklist.h"
#include "ctc_error.h"


#include "ctc_l2.h"
#include "ctc_pdu.h"
#include "sys_usw_common.h"
#include "sys_usw_port_api.h"
#include "sys_usw_opf.h"
#include "sys_usw_ftm.h"
#include "sys_usw_l2_fdb.h"
#include "sys_usw_learning_aging.h"
#include "sys_usw_aps.h"
#include "sys_usw_dma.h"
#include "sys_usw_vlan.h"
#include "sys_usw_stp.h"
#include "sys_usw_register.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_fdb_sort.h"
#include "sys_usw_qos.h"
#include "sys_usw_security.h"
#include "sys_usw_xdata_api.h"
#include "sys_usw_stats_api.h"
#include "drv_api.h"
#include "sys_usw_nexthop_api.h"

sys_l2_master_t* pl2_usw_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};

extern int32 sys_usw_aging_get_aging_timer(uint8 lchip, uint8 domain_type, uint32 key_index, uint8* p_timer);

extern int32 sys_usw_l2_fdb_wb_sync(uint8 lchip,uint32 app_id);
extern int32 _sys_usw_l2_wb_init(uint8 lchip);

extern int32 sys_usw_l2_fdb_wb_restore(uint8 lchip);
extern int32 sys_usw_flow_stats_alloc_fid_type(uint8 lchip);
extern int32 _sys_usw_l2_ad_spool_alloc_index(sys_l2_ad_t* p_ad, void* user_data);
extern int32 _sys_usw_l2_ad_spool_free_index(sys_l2_ad_t* p_ad, void* user_data);

STATIC int32
_sys_usw_l2_write_hw(uint8 lchip, sys_l2_info_t* psys);
STATIC int32 _sys_usw_l2_set_fid_property(uint8 lchip, uint16 fid_id, uint32 fid_prop, uint32 value);

STATIC int32 _sys_usw_l2_xdata_check(uint8 lchip, sys_l2_info_t* psys);

#if defined(DUET2)
STATIC int32 _sys_usw_l2_get_dstmp_profile_cb(void* p_bucket_node, uint32 cur_hash_node_id, uint32 cur_list_id, void* user_data);
#endif

/****************************************************************************
 *
 * Function
 *
 *****************************************************************************/
int32 sys_usw_l2_fdb_change_mem_cb(uint8 lchip, void*user_data);
int32
sys_usw_l2_dump_db(uint8 lchip, sal_file_t p_f,ctc_global_dump_db_t* p_dump_param);
/* normal fdb hash opearation*/


uint32
_sys_usw_l2_fdb_hash_make(sys_l2_node_t* node)
{
    return ctc_hash_caculate(sizeof(mac_addr_t)+sizeof(uint16), &(node->mac));
}

bool
_sys_usw_l2_fdb_hash_compare(sys_l2_node_t* stored_node, sys_l2_node_t* lkup_node)
{
    if (!stored_node || !lkup_node)
    {
        return TRUE;
    }

    if (!sal_memcmp(stored_node->mac, lkup_node->mac, CTC_ETH_ADDR_LEN)
        && (stored_node->fid == lkup_node->fid))
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_l2_fdb_hash_add(uint8 lchip, sys_l2_node_t* p_fdb_node)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    if (NULL == ctc_hash_insert(pl2_usw_master[lchip]->fdb_hash, p_fdb_node))
    {
        return CTC_E_NO_MEMORY;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_fdb_hash_remove(uint8 lchip, sys_l2_node_t* p_fdb_node)
{
    if (!ctc_hash_remove(pl2_usw_master[lchip]->fdb_hash, p_fdb_node))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [FDB] Hash remove failed \n");
        return CTC_E_NOT_EXIST;

    }

    return CTC_E_NONE;
}

STATIC sys_l2_node_t*
_sys_usw_l2_fdb_hash_lkup(uint8 lchip, mac_addr_t* mac, uint16 fid)
{
    sys_l2_node_t node;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&node, 0, sizeof(node));

    node.fid = fid;
    sal_memcpy(&node.mac, mac, sizeof(mac_addr_t));

    return ctc_hash_lookup(pl2_usw_master[lchip]->fdb_hash, &node);
}
STATIC void*
_sys_usw_l2_fid_node_lkup(uint8 lchip, uint16 fid)
{
    sys_l2_fid_node_t* p_lkup;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    p_lkup = ctc_vector_get(pl2_usw_master[lchip]->fid_vec, fid);

    return p_lkup;

}
STATIC uint32
_sys_usw_l2_ad_hash_make(sys_l2_ad_update_node_t* p_ad_node)
{
    return ctc_hash_caculate(sizeof(uint32), &p_ad_node->ad_index);
}
STATIC bool

_sys_usw_l2_ad_hash_cmp(sys_l2_ad_update_node_t* p_ad_node1, sys_l2_ad_update_node_t* p_ad_node2)
{
    if(p_ad_node1->ad_index != p_ad_node2->ad_index)
    {
        return FALSE;
    }
    return TRUE;
}

STATIC int32
_sys_usw_l2_dsmac_spool_add(uint8 lchip, sys_l2_ad_t  *l2_ad,  sys_l2_ad_t**  pp_ad)
{
    l2_ad->param.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_add2(pl2_usw_master[lchip]->ad_spool, l2_ad, NULL, (void*)pp_ad));

    return 0;
}

STATIC int32
_sys_usw_l2_dsmac_spool_remove(uint8 lchip, sys_l2_ad_t  *l2_ad_old, sys_l2_ad_t** p_ad_get)
{
    DsMac_m dsmac;
    sys_l2_ad_t l2_ad;
    uint32 cmd = 0;

    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, l2_ad_old->index, cmd, &dsmac));
    l2_ad.param.ds_mac = &dsmac;
    l2_ad.param.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_remove2(pl2_usw_master[lchip]->ad_spool, &l2_ad, (void*)p_ad_get));

    return 0;
}

STATIC uint16
_sys_usw_l2_get_fid_flag(uint8 lchip, uint16 fid)
{
    sys_l2_fid_node_t* p_fid_node = NULL;
    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, fid);
    return p_fid_node ? (p_fid_node->flag) : 0;
}
uint16
sys_usw_l2_get_fid_flag(uint8 lchip, uint16 fid)
{
    return _sys_usw_l2_get_fid_flag(lchip, fid);
}

int32
sys_usw_l2_get_dsmac_base(uint8 lchip, sys_l2_dsmac_base_type_t type)
{
    return pl2_usw_master[lchip]->dsmac_base[type];
}

STATIC int32
_sys_usw_l2_decode_dsmac(uint8 lchip, sys_l2_info_t* psys, uint32 ad_index, void* p_ds_mac)
{
    uint32 destmap = 0;
    uint32 temp_flag = 0;
    uint32 temp_gport = 0;
    DsMac_m ds_mac;
    uint32  cmd = 0;
    uint16  ecmp_group_id = 0;

    CTC_PTR_VALID_CHECK(psys);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Read dsmac, ad_index:0x%x\n", ad_index);

    if (p_ds_mac == NULL)
    {
        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ad_index, cmd, &ds_mac));
    }
    else
    {
        sal_memcpy(&ds_mac, p_ds_mac, sizeof(DsMac_m));
    }

    psys->ad_index        = ad_index;
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_IS_STATIC, GetDsMac(V, isStatic_f, &ds_mac));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_BIND_PORT, GetDsMac(V, srcMismatchDiscard_f, &ds_mac));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_PROTOCOL_ENTRY, GetDsMac(V, protocolExceptionEn_f, &ds_mac));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_COPY_TO_CPU, (GetDsMac(V, macDaExceptionEn_f, &ds_mac) && !GetDsMac(V, u3Type_f, &ds_mac)));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_SRC_DISCARD, GetDsMac(V, srcDiscard_f, &ds_mac));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_SELF_ADDRESS, GetDsMac(V, localAddress_f, &ds_mac));
    SYS_L2_OP_FLAG(temp_flag, CTC_L2_FLAG_REMOTE_DYNAMIC, GetDsMac(V, userDefine_f, &ds_mac));

    ecmp_group_id = !GetDsMac(V, nextHopPtrValid_f, &ds_mac) ?(GetDsMac(V, ecmpGroupIdHighBits_f, &ds_mac) << 7 |
    GetDsMac(V, tunnelPacketType_f, &ds_mac) << 4 |GetDsMac(V, tunnelPayloadOffset_f, &ds_mac)) : 0 ;


    /* | default| tid| gport| vport|*/
    if (ad_index >= sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK))
    {
        psys->rsv_ad_index = 1;
    }
    else if (ad_index == pl2_usw_master[lchip]->ad_index_drop)
    {
        CTC_SET_FLAG(temp_flag, CTC_L2_FLAG_DISCARD);
    }
    else if (!ecmp_group_id && !GetDsMac(V, nextHopPtrValid_f, &ds_mac) && !GetDsMac(V, u1Type_f, &ds_mac) && (SYS_FDB_DISCARD_FWD_PTR == GetDsMac(V, dsFwdPtr_f, &ds_mac)))
    {
        CTC_SET_FLAG(temp_flag, CTC_L2_FLAG_DISCARD);
    }

    if(GetDsMac(V, srcDiscard_f, &ds_mac) &&  GetDsMac(V, macSaExceptionEn_f, &ds_mac))
    {
        CTC_SET_FLAG(temp_flag, CTC_L2_FLAG_SRC_DISCARD_TOCPU);
    }
    /*decode addr type*/
    psys->addr_type = SYS_L2_ADDR_TYPE_UC;
    destmap = GetDsMac(V, adDestMap_f, &ds_mac);


    psys->is_logic_port = GetDsMac(V, learnSource_f, &ds_mac);

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_IS_STATIC) && /*mcast is static.*/
        (GetDsMac(V, nextHopPtrValid_f, &ds_mac) || (GetDsMac(V, u1Type_f, &ds_mac) == 1) || CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_DISCARD)) &&
        IS_MCAST_DESTMAP(destmap))
    {
        if (IS_DEFAULT_ENTRY_INDEX(ad_index))
        {
            psys->addr_type = SYS_L2_ADDR_TYPE_DEFAULT;
            psys->addr.l2df_addr.l2mc_grp_id = (destmap &0xFFFF);
            if (GetDsMac(V, categoryIdValid_f, &ds_mac))
            {
                psys->addr.l2df_addr.cid = GetDsMac(V, categoryId_f, &ds_mac);
            }
        }
        else if(!psys->is_logic_port)
        {
            psys->addr_type = SYS_L2_ADDR_TYPE_MC;
            psys->addr.l2mc_addr.l2mc_grp_id = (destmap &0xFFFF);
            if (GetDsMac(V, categoryIdValid_f, &ds_mac) && !GetDsMac(V, u3Type_f, &ds_mac))
            {
                psys->addr.l2mc_addr.cid = GetDsMac(V, categoryId_f, &ds_mac);
            }
        }
    }

    psys->merge_dsfwd = GetDsMac(V, nextHopPtrValid_f, &ds_mac);

    if (psys->merge_dsfwd)
    {
        psys->aps_valid = GetDsMac(V, adApsBridgeEn_f, &ds_mac);
        destmap = GetDsMac(V, adDestMap_f, &ds_mac);
        psys->dsnh_offset = GetDsMac(V, adNextHopPtr_f, &ds_mac);
        psys->ecmp_valid = SYS_IS_ECMP_DESTMAP(destmap);
        if (psys->ecmp_valid)
        {
            psys->destmap = SYS_DECODE_ECMP_DESTMAP(destmap);
        }
        else
        {
            psys->destmap = destmap;
        }
    }
    else
    {
        ecmp_group_id = GetDsMac(V, ecmpGroupIdHighBits_f, &ds_mac) << 7 |
        GetDsMac(V, tunnelPacketType_f, &ds_mac) << 4 |
        GetDsMac(V, tunnelPayloadOffset_f, &ds_mac) ;

        psys->ecmp_valid = !GetDsMac(V, payloadSelect_f, &ds_mac) && (ecmp_group_id != 0);

        psys->fwd_ptr    = GetDsMac(V, dsFwdPtr_f, &ds_mac);
        
        if (psys->ecmp_valid)
        {
            psys->destmap = ecmp_group_id ;
        }
    }

    if(psys->addr_type == SYS_L2_ADDR_TYPE_UC)
    {
        psys->addr.l2_addr.flag = temp_flag;

        if (psys->is_logic_port)
        {
            temp_gport = GetDsMac(V, logicSrcPort_f, &ds_mac);
            psys->addr.l2_addr.is_logic_port = 1;
        }
        else
        {
            temp_gport = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(GetDsMac(V, globalSrcPort_f, &ds_mac));
        }
        psys->addr.l2_addr.gport = temp_gport;
        if ((GetDsMac(V, categoryIdValid_f, &ds_mac) || GetDsMac(V, categoryIdOrServiceId_f, &ds_mac)) && !GetDsMac(V, u3Type_f, &ds_mac))
        {
            psys->addr.l2_addr.cid = GetDsMac(V, categoryId_f, &ds_mac);
        }
    }
    else if(psys->addr_type == SYS_L2_ADDR_TYPE_MC)
    {
        psys->addr.l2mc_addr.flag = temp_flag;
    }

    psys->share_grp_en = !GetDsMac(V, fastLearningEn_f, &ds_mac);

    return CTC_E_NONE;
}

STATIC int32
sys_usw_l2_decode_dsmac(uint8 lchip, sys_l2_info_t* psys, uint32 ad_index, void* p_ds_mac)
{
    int32 ret = 0;
    ret = MCHIP_FDB(lchip)->dsmac_decode? MCHIP_FDB(lchip)->dsmac_decode(lchip, psys,  ad_index, p_ds_mac)
    : _sys_usw_l2_decode_dsmac(lchip, psys, ad_index, p_ds_mac);
    return ret;
}

STATIC int32
_sys_usw_l2_encode_dsmacdefault(uint8 lchip, void* p_dsmacdefault, sys_l2_info_t* psys)
{
    uint16 cid = 0;
    /* uint32 cmd = 0; */
    /* uint32 value = 0; */

    /*dsmacdefault for xdata (keep top, avoid data overwriting !!!)*/
    if (DRV_FROM_AT(lchip))
    {
        SetDsMacDefault(V, isDsMacDefault_f, p_dsmacdefault, 1);
        if(psys->xdata_en) /*enable xdata*/
        {
            SetDsMacDefault(A, xAdData_f, p_dsmacdefault, psys->xdata.value);
            SetDsMacDefault(V, xAdEn_f, p_dsmacdefault, 1);
            if(CTC_IS_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_CID))
            {
                SetDsMacDefault(V, categoryIdValid_f, p_dsmacdefault, 0);
            }
        }
    }

    if (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && psys->revert_default)
    {
        cid = psys->addr.l2df_addr.cid;
        SetDsMacDefault(V, u_g0_dsFwdPtr_f, p_dsmacdefault, SYS_FDB_DISCARD_FWD_PTR);
        SetDsMacDefault(V, protocolExceptionEn_f, p_dsmacdefault, 1);
        SetDsMacDefault(V, unknownMcastExceptionSubIndexBase_f, p_dsmacdefault, 63);
    }
    else if (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && !psys->revert_default)
    {
        cid = psys->addr.l2df_addr.cid;
        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT))
        {
            SetDsMacDefault(V, learnSource_f, p_dsmacdefault, 1);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_LEARNING_DISABLE))
        {
            SetDsMacDefault(V, conversationCheckEn_f, p_dsmacdefault, 1);
        }
        else
        {
            SetDsMacDefault(V, conversationCheckEn_f, p_dsmacdefault, 0);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_PROTOCOL_EXCP_TOCPU))
        {
            SetDsMacDefault(V, protocolExceptionEn_f, p_dsmacdefault, 1);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_PORT_MAC_AUTH))
        {
            SetDsMacDefault(V, srcMismatchDiscard_f, p_dsmacdefault, 1);
        }

        /*port mac auth also config this,so the global src port is 1008 (0x3f << 4), the mac auth can work normally*/
        SetDsMacDefault(V, unknownMcastExceptionSubIndexBase_f, p_dsmacdefault, 63);
        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_VLAN_MAC_AUTH))
        {
            uint32 cmd = 0;
            uint32 value = 0;
            SetDsMacDefault(V, srcDiscard_f, p_dsmacdefault, 1);
            cmd = DRV_IOR(DsMacDefault_t, DsMacDefault_macSaExceptionEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, psys->ad_index, cmd, &value));
            SetDsMacDefault(V, macSaExceptionEn_f, p_dsmacdefault, value);
        }

        SetDsMacDefault(V, u1Type_f, p_dsmacdefault, 1);
        SetDsMacDefault(V, u_g1_dsFwd_nextHopExt_f, p_dsmacdefault, psys->nh_ext);
        SetDsMacDefault(V, u_g1_dsFwd_destMap_f, p_dsmacdefault, SYS_ENCODE_MCAST_IPE_DESTMAP(psys->addr.l2df_addr.l2mc_grp_id));
        SetDsMacDefault(V, u_g1_dsFwd_nextHopPtr_f, p_dsmacdefault, psys->dsnh_offset);
        SetDsMacDefault(V, u_g1_dsFwd_apsBridgeEn_f, p_dsmacdefault, psys->aps_valid);
        SetDsMacDefault(V, u_g1_dsFwd_bypassIngressEdit_f, p_dsmacdefault, psys->by_pass_ingress_edit);
        SetDsMacDefault(V, isConversation_f, p_dsmacdefault, 0);
    }

    if (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && !psys->revert_default)
    {
        SetDsMacDefault(V, isStatic_f, p_dsmacdefault, 1);
    }

    SetDsMacDefault(V, stormCtlEn_f, p_dsmacdefault, 1);
    SetDsMacDefault(V, fastLearningEn_f, p_dsmacdefault, (psys->share_grp_en)? 0 : 1);
    SetDsMacDefault(V, macUnKnown_f, p_dsmacdefault, 1);

    if (cid)
    {
        SetDsMacDefault(V, categoryIdValid_f, p_dsmacdefault, 1);
        SetDsMacDefault(V, categoryId_f, p_dsmacdefault, cid);
    }

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_l2_encode_dsmac(uint8 lchip, DsMac_m* p_dsmac, sys_l2_info_t* psys)
{
    uint8  gchip    = 0;
    uint16  cid = 0;
    uint16 group_id = 0;
    uint32   temp_flag = 0;
    uint32   cmd = 0;
    uint32   value = 0;
    uint8 xgpon_en = 0;

    CTC_PTR_VALID_CHECK(psys);
    CTC_PTR_VALID_CHECK(p_dsmac);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);


    sal_memset(p_dsmac, 0, sizeof(DsMac_m));
	sys_usw_global_get_xgpon_en(lchip, &xgpon_en);

    /* for TsingMa.MX and subsequent chips' default action process */
    if (DRV_FROM_TMM(lchip) && psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT)
    {
        return _sys_usw_l2_encode_dsmacdefault(lchip, p_dsmac, psys);
    }
    if (MCHIP_FDB(lchip)->dsmac_encode)
    {
        psys->xgpon_en = xgpon_en;
        return MCHIP_FDB(lchip)->dsmac_encode(lchip, p_dsmac, psys);
    }


    /* l2 uc*/
    if (psys->addr_type == SYS_L2_ADDR_TYPE_UC)
    {
        cid = CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_PON_EN)? 0 : psys->addr.l2_addr.cid;
        temp_flag = psys->addr.l2_addr.flag;
        SetDsMac(V, sourcePortCheckEn_f, p_dsmac, 1);

        if (!CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_IS_STATIC) && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_DISCARD)
            && !pl2_usw_master[lchip]->station_move_no_learn)
        {
            /*For DUET2 xgpon application, if bind port enable do not learning*/
            if (!DRV_IS_DUET2(lchip) || !xgpon_en || !CTC_FLAG_ISSET(temp_flag,CTC_L2_FLAG_BIND_PORT))
            {
                SetDsMac(V, srcMismatchLearnEn_f, p_dsmac, 1);
            }
        }

        if (CTC_FLAG_ISSET(temp_flag,CTC_L2_FLAG_BIND_PORT))
        {
            SetDsMac(V, srcMismatchDiscard_f, p_dsmac, 1);
        }

        if (psys->is_logic_port)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " DsMac.logic_port 0x%x\n", psys->addr.l2_addr.gport);
            SetDsMac(V, learnSource_f, p_dsmac, 1);
            SetDsMac(V, logicSrcPort_f, p_dsmac, psys->addr.l2_addr.gport);
            SetDsMac(V, logicDestPortValid_f, p_dsmac, 1);

            if (!DRV_IS_DUET2(lchip) && psys->addr.l2_addr.policer_id &&
                 xgpon_en && CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_PON_EN))
            {
                uint16 policer_ptr = 0;
                uint8 cos_index = 0;
                sys_qos_policer_param_t policer_param;

                sal_memset(&policer_param, 0, sizeof(sys_qos_policer_param_t));
                policer_param.glb_policer = 1;
                policer_param.policer_id = psys->addr.l2_addr.policer_id;
                policer_param.sys_policer_type = SYS_QOS_POLICER_TYPE_FLOW;
                CTC_ERROR_RETURN(sys_usw_qos_policer_index_get(lchip, &policer_param));
                cos_index = psys->addr.l2_addr.cid; /* cid used for cos_index when Pon_en */
                if ((cos_index && !policer_param.is_bwp) || (cos_index > (MCHIP_CAP(SYS_CAP_QOS_POLICER_MAX_COS_LEVEL)-1)))
                {
                    return CTC_E_INVALID_PARAM;
                }
                policer_ptr = policer_param.policer_ptr + cos_index;

                SetDsMac(V, macDaPolicerEn_f, p_dsmac, 1);
                SetDsMac(V, stpCheckDisable_f, p_dsmac, (policer_ptr >> 12) & 0x1);
                SetDsMac(V, macDaExceptionEn_f, p_dsmac, (policer_ptr >> 11) & 0x1);
                SetDsMac(V, exceptionSubIndex_f, p_dsmac, (policer_ptr >> 9) & 0x3);
                SetDsMac(V, categoryIdValid_f, p_dsmac, (policer_ptr >> 8) & 0x1);
                SetDsMac(V, categoryId_f, p_dsmac, (policer_ptr) & 0xFF);
            }
        }
        else
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " DsMac.gport 0x%x\n", psys->addr.l2_addr.gport);
            SetDsMac(V, learnSource_f, p_dsmac, 0);
            SetDsMac(V, globalSrcPort_f, p_dsmac, SYS_MAP_CTC_GPORT_TO_DRV_GPORT(psys->addr.l2_addr.gport));
        }

        SetDsMac(V, isConversation_f, p_dsmac, 0);
        if (!psys->merge_dsfwd)
        {
            if (psys->ecmp_valid)
            {
                /* ecmpGroupId(9,0) = 
                {
                    ecmpGroupIdHighBits(2, 0), tunnelPacketType(2, 0)tunnelPayloadOffset(3, 0)
                }
                */
                /*-SetDsMac(V, u1_g1_ecmpEn_f, p_dsmac, 1);
                */
                SetDsMac(V, ecmpGroupIdHighBits_f,   p_dsmac, ((psys->destmap >> 7) & 0x7));
                SetDsMac(V, tunnelPacketType_f,      p_dsmac, ((psys->destmap >> 4) & 0x7));
                SetDsMac(V, tunnelPayloadOffset_f,   p_dsmac,  (psys->destmap & 0xF));
                SetDsMac(V, dsFwdPtr_f, p_dsmac, psys->fwd_ptr);
                SetDsMac(V, priorityPathEn_f,   p_dsmac,  (psys->h_ecmp));
            }
            else
            {
                SetDsMac(V, u1Type_f, p_dsmac, 0);
                SetDsMac(V, dsFwdPtr_f, p_dsmac, psys->fwd_ptr);
            }
        }
        else
        {
            uint8 adjust_len_idx = 0;
            SetDsMac(V, nextHopPtrValid_f, p_dsmac, 1);
            SetDsMac(V, adNextHopExt_f, p_dsmac, psys->nh_ext);
            SetDsMac(V, adDestMap_f, p_dsmac, psys->destmap);
            SetDsMac(V, adNextHopPtr_f, p_dsmac,psys->dsnh_offset);
            if(0 != psys->adjust_len)
            {
                sys_usw_lkup_adjust_len_index(lchip, psys->adjust_len, &adjust_len_idx);
                SetDsMac(V, adLengthAdjustType_f, p_dsmac, adjust_len_idx);
            }
            else
            {
                SetDsMac(V, adLengthAdjustType_f, p_dsmac, 0);
            }
            SetDsMac(V, adApsBridgeEn_f, p_dsmac, psys->aps_valid);
            SetDsMac(V, adCloudSecEn_f, p_dsmac, psys->cloud_sec_en);
            SetDsMac(V, adBypassIngressEdit_f, p_dsmac, psys->by_pass_ingress_edit);

            /* TsingMa.MX */
            SetDsMac(V, u1Type_f, p_dsmac, 1);
            SetDsMac(V, nextHopExt_f, p_dsmac, psys->nh_ext);
            SetDsMac(V, destMap_f, p_dsmac, psys->destmap);
            SetDsMac(V, nextHopPtr_f, p_dsmac,psys->dsnh_offset);
            SetDsMac(V, apsBridgeEn_f, p_dsmac, psys->aps_valid);
            SetDsMac(V, bypassIngressEdit_f, p_dsmac, psys->by_pass_ingress_edit);
            SetDsMac(V, tunnelEcmpHighBit_f, p_dsmac, psys->tunnel_ecmp_high);

        }

        /* dsmac for router mac match */
        if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_RMAC_MATCH))
        {
            SetDsMac(V, isRouterMac_f, p_dsmac, 1);
        }

    }
    else if (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && psys->revert_default)
    {
        cid = psys->addr.l2df_addr.cid;
        SetDsMac(V, dsFwdPtr_f, p_dsmac, SYS_FDB_DISCARD_FWD_PTR);
        SetDsMac(V, protocolExceptionEn_f, p_dsmac, 1);
        /*TBD sub index base need consider more*/
        SetDsMac(V, unknownMcastExceptionSubIndexBase_f, p_dsmac, 63);
        SetDsMac(V, bcastExceptionSubIndexAddition_f, p_dsmac, 0);/*D2*/
        SetDsMac(V, unknownUcastExceptionSubIndexAddition_f, p_dsmac, 0);/*D2*/
        if (!xgpon_en && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A) && DRV_IS_TSINGMA(lchip))
        {
            SetDsMac(V, macDaPolicerEn_f, p_dsmac, 1);
        }
    }
    else if (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && !psys->revert_default)
    {
        cid = psys->addr.l2df_addr.cid;
        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT))
        {
            SetDsMac(V, learnSource_f, p_dsmac, 1);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_LEARNING_DISABLE))
        {
            SetDsMac(V, conversationCheckEn_f, p_dsmac, 1);
        }
        else
        {
            SetDsMac(V, conversationCheckEn_f, p_dsmac, 0);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_PROTOCOL_EXCP_TOCPU))
        {
            SetDsMac(V, protocolExceptionEn_f, p_dsmac, 1);
        }

        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_PORT_MAC_AUTH))
        {
            SetDsMac(V, srcMismatchDiscard_f, p_dsmac, 1);
        }
        /*port mac auth also config this,so the global src port is 1008 (0x3f << 4), the mac auth can work normally*/
        SetDsMac(V, unknownMcastExceptionSubIndexBase_f, p_dsmac, 63);
        SetDsMac(V, bcastExceptionSubIndexAddition_f, p_dsmac, 0);/*D2*/
        SetDsMac(V, unknownUcastExceptionSubIndexAddition_f, p_dsmac, 0);/*D2*/
        if (CTC_FLAG_ISSET(psys->addr.l2df_addr.flag, CTC_L2_DFT_VLAN_FLAG_VLAN_MAC_AUTH))
        {
            SetDsMac(V, srcDiscard_f, p_dsmac, 1);
            cmd = DRV_IOR(DsMac_t, DsMac_macSaExceptionEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, psys->ad_index, cmd, &value));
            SetDsMac(V, macSaExceptionEn_f, p_dsmac, value);
        }

        /* always use nexthop */
        SetDsMac(V, nextHopPtrValid_f, p_dsmac, 1);
        SetDsMac(V, adDestMap_f, p_dsmac, SYS_ENCODE_MCAST_IPE_DESTMAP(psys->addr.l2df_addr.l2mc_grp_id));
        SetDsMac(V, adNextHopPtr_f, p_dsmac, 0);
        SetDsMac(V, isConversation_f, p_dsmac, 0);
        if (!xgpon_en && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A) && DRV_IS_TSINGMA(lchip))
        {
            SetDsMac(V, macDaPolicerEn_f, p_dsmac, 1);
        }

        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gchip=%d, group_id=0x%x\n", gchip, group_id);
    }
    else  /* (psys->flag.type_l2mc)*/
    {
        cid = psys->addr.l2mc_addr.cid;
        temp_flag = psys->addr.l2mc_addr.flag;
        /* always use nexthop */
        SetDsMac(V, nextHopPtrValid_f, p_dsmac, 1);
        SetDsMac(V, adDestMap_f, p_dsmac, SYS_ENCODE_MCAST_IPE_DESTMAP(psys->addr.l2mc_addr.l2mc_grp_id));
        SetDsMac(V, adNextHopPtr_f, p_dsmac, 0);
        SetDsMac(V, isConversation_f, p_dsmac, 0);

        /* TsingMa.MX */
        SetDsMac(V, u1Type_f, p_dsmac, 1);
        SetDsMac(V, destMap_f, p_dsmac, SYS_ENCODE_MCAST_IPE_DESTMAP(psys->addr.l2mc_addr.l2mc_grp_id));
        SetDsMac(V, nextHopPtr_f, p_dsmac, 0);

        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gchip=%d, group_id=0x%x\n", gchip, group_id);
    }

    if ((CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_IS_STATIC)) || (psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT && !psys->revert_default))
    {
        SetDsMac(V, isStatic_f, p_dsmac, 1);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_SELF_ADDRESS))
    {
        SetDsMac(V, localAddress_f, p_dsmac, 1);
    }
    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_DISCARD))
    {
        SetDsMac(V, nextHopPtrValid_f, p_dsmac, 0);
        SetDsMac(V, dsFwdPtr_f, p_dsmac, SYS_FDB_DISCARD_FWD_PTR);
        SetDsMac(V, ecmpGroupIdHighBits_f,   p_dsmac, 0);
        SetDsMac(V, tunnelPacketType_f,      p_dsmac, 0);
        SetDsMac(V, tunnelPayloadOffset_f,   p_dsmac, 0);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_SRC_DISCARD))
    {
        SetDsMac(V, srcDiscard_f, p_dsmac, 1);
        SetDsMac(V, macSaExceptionEn_f, p_dsmac, 0);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_SRC_DISCARD_TOCPU))
    {
        SetDsMac(V, srcDiscard_f, p_dsmac, 1);
        SetDsMac(V, macSaExceptionEn_f, p_dsmac, 1);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_COPY_TO_CPU))
    {
        SetDsMac(V, u3Type_f, p_dsmac, 0);
        SetDsMac(V, macDaExceptionEn_f, p_dsmac, 1);
        /* Reserved for normal MACDA copy_to_cpu */
        SetDsMac(V, exceptionSubIndex_f, p_dsmac, CTC_L2PDU_ACTION_INDEX_MACDA);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_PROTOCOL_ENTRY))
    {
        SetDsMac(V, protocolExceptionEn_f, p_dsmac, 1);
    }

    if (CTC_FLAG_ISSET(temp_flag, CTC_L2_FLAG_REMOTE_DYNAMIC))
    {
        SetDsMac(V, userDefine_f, p_dsmac, 1);
    }

    SetDsMac(V, stormCtlEn_f, p_dsmac, 1);
    SetDsMac(V, fastLearningEn_f, p_dsmac, (psys->share_grp_en)?0:1);

    /*dsmac for cid*/
    if (cid)
    {
        SetDsMac(V, categoryIdValid_f, p_dsmac, 1);
        SetDsMac(V, categoryId_f, p_dsmac, cid);
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_acc_lookup_mac_fid(uint8 lchip, mac_addr_t mac, uint16 fid, mac_lookup_result_t* pr)
{
    drv_acc_in_t  in;
    drv_acc_out_t out;
    DsFibHost0MacHashKey_m fdb_key;
    hw_mac_addr_t   hw_mac = {0};

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&in, 0, sizeof(in));
    sal_memset(&out, 0, sizeof(out));
    sal_memset(pr, 0, sizeof(mac_lookup_result_t));
    sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));

    FDB_SET_HW_MAC(hw_mac, mac);
    SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, fid);
    SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
    in.tbl_id = DsFibHost0MacHashKey_t;
    in.data = &fdb_key;
    in.type = DRV_ACC_TYPE_LOOKUP;
    in.op_type = DRV_ACC_OP_BY_KEY;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

    pr->ad_index  = out.ad_index;
    pr->key_index = out.key_index;
    pr->hit       = out.is_hit;
    pr->conflict  = out.is_conflict;
    pr->pending   = out.is_pending;
    if (pr->pending)
    {
        pr->hit       = 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_fdb_calc_index(uint8 lchip, mac_addr_t mac, uint16 fid, sys_l2_calc_index_t* p_index, uint8 except_level)
{
    drv_acc_in_t  in;
    drv_acc_out_t out;
    uint8 hash_key[12] = {0};
    DsFibHost0MacHashKey_m fdb_key;

    CTC_PTR_VALID_CHECK(p_index);
    sal_memset(&in, 0, sizeof(drv_acc_in_t));
    sal_memset(&out, 0, sizeof(drv_acc_out_t));

    if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
    {
        hash_key[0] = 0x09;
        hash_key[2] = (fid & 0x3) << 6;
        hash_key[3] = (fid >> 2) & 0xFF;
        hash_key[4] = ((fid >> 10) & 0xF) | ((mac[5] & 0xF) << 4);
        hash_key[5] = (mac[5] >> 4) | ((mac[4] & 0xF) << 4);
        hash_key[6] = (mac[4] >> 4) | ((mac[3] & 0xF) << 4);
        hash_key[7] = (mac[3] >> 4) | ((mac[2] & 0xF) << 4);
        hash_key[8] = (mac[2] >> 4) | ((mac[1] & 0xF) << 4);
        hash_key[9] = (mac[1] >> 4) | ((mac[0] & 0xF) << 4);
        hash_key[10] = mac[0] >> 4;
    }
    else
    {
        hw_mac_addr_t   hw_mac = {0};
        sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));

        FDB_SET_HW_MAC(hw_mac, mac);
        SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, fid);
        SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
        SetDsFibHost0MacHashKey(V, hashType_f, &fdb_key, DRV_ENUM(DRV_FIBHOST0PRIMARYHASHTYPE_MAC));
        SetDsFibHost0MacHashKey(V, valid_f, &fdb_key, 1);
    }

    in.data = DRV_FROM_TMM(lchip)? (void*)(&fdb_key) : (void*)hash_key;
    in.type = DRV_ACC_TYPE_CALC;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.op_type = DRV_ACC_OP_BY_KEY;
    in.level = except_level;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    CTC_ERROR_RETURN(drv_acc_fdb_calc_index(lchip, &in, &out));

    p_index->index_cnt = out.query_cnt;
    sal_memcpy(p_index->key_index, out.data, p_index->index_cnt * sizeof(uint32));
    sal_memcpy(p_index->level, out.out_level, p_index->index_cnt * sizeof(uint8));
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_decode_dskey(uint8 lchip, sys_l2_info_t* psys, void* p_dskey)
{
    uint8 xgpon_en = 0;
    hw_mac_addr_t   hw_mac;
    uint8           timer = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    psys->addr.l2_addr.fid = GetDsFibHost0MacHashKey(V, vsiId_f, p_dskey);

    GetDsFibHost0MacHashKey(A, mappedMac_f, p_dskey, hw_mac);
    SYS_USW_SET_USER_MAC(psys->addr.l2_addr.mac, hw_mac);
    psys->ad_index  = GetDsFibHost0MacHashKey(V, dsAdIndex_f, p_dskey);
    sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
    if (xgpon_en && DRV_IS_TSINGMA(lchip))
    {
        psys->ad_index = psys->ad_index & 0xFFFF;
    }
    psys->key_valid = GetDsFibHost0MacHashKey(V, valid_f, p_dskey);
    psys->pending   = GetDsFibHost0MacHashKey(V, pending_f, p_dskey);
    CTC_ERROR_RETURN(sys_usw_aging_get_aging_timer(lchip, SYS_AGING_DOMAIN_MAC_HASH, psys->key_index, &timer));
    if(timer == 0)
    {
        CTC_SET_FLAG(psys->addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE);
    }

    return CTC_E_NONE;
}

/*
if ad_index == NULL, needn't to get ad_index
*/
STATIC uint8
_sys_usw_l2_black_hole_lookup(uint8 lchip, mac_addr_t mac, uint32* key_index, uint32* ad_index)
{
    uint32 index = 0;
    hw_mac_addr_t drv_mac;
    uint32 cmd = DRV_IOR(DsFibMacBlackHoleHashKey_t, DRV_ENTRY_FLAG);
    DsFibMacBlackHoleHashKey_m fib_mac_hash_key;
    hw_mac_addr_t hw_mac;

    FDB_SET_HW_MAC(hw_mac, mac);

    for(index=0; index < SYS_L2_MAX_BLACK_HOLE_ENTRY; index++)
    {
        if(CTC_BMP_ISSET(pl2_usw_master[lchip]->mac_fdb_bmp, index))
        {
            DRV_IOCTL(lchip, index, cmd, &fib_mac_hash_key);

            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "read DsFibMacBlackHoleHashKey_t index:%d\n", index);

            if(!GetDsFibMacBlackHoleHashKey(V, valid_f, &fib_mac_hash_key))
            {
                continue;
            }

            GetDsFibMacBlackHoleHashKey(A, mappedMac_f, &fib_mac_hash_key, &drv_mac);
            if(!sal_memcmp(&hw_mac, &drv_mac, sizeof(hw_mac_addr_t)))
            {
                *key_index = index;
                break;
            }
        }
    }

    if(index != SYS_L2_MAX_BLACK_HOLE_ENTRY)
    {
        if(ad_index)
        {
            *ad_index = GetDsFibMacBlackHoleHashKey(V, dsAdIndex_f, &fib_mac_hash_key);
        }

        return 1;
    }

    *key_index = 0xFFFFFFFF;
    return 0;
}

STATIC int32
_sys_usw_l2_update_logic_dsmac(uint8 lchip, void* data, void* change_nh_param)
{
    sys_l2_vport_2_nhid_t* p_node = (sys_l2_vport_2_nhid_t*)data;
    uint32 cmd  = 0;
    DsMac_m   dsmac;
    uint32 fwd_offset = 0;
    sys_nh_info_dsnh_t* p_dsnh_info = change_nh_param;
    int32 ret = 0;

    /*if true funtion was called because nexthop update,if false funtion was called because using dsfwd*/
    if (p_dsnh_info->need_lock)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Add Lock \n");
        L2_LOCK;
    }

    p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, p_dsnh_info->chk_data);
    if (!p_node || p_node->nhid != p_dsnh_info->nhid)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "bind reserve nh update fail, nh & logic bind is Null!\n");
		ret =  CTC_E_NONE;
        goto out;
    }

    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_node->ad_idx, cmd, &dsmac);

    if (p_dsnh_info->merge_dsfwd == 2)
    {
        /*update ad from merge dsfwd to using dsfwd*/

        /*1. alloc dsfwd*/
        CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, p_node->nhid, &fwd_offset, 0, CTC_FEATURE_L2), ret, out);

        /*2. update ad*/
        SetDsMac(V, nextHopPtrValid_f, &dsmac, 0);
        SetDsMac(V, adDestMap_f, &dsmac, 0);
        SetDsMac(V, adNextHopPtr_f, &dsmac, 0);
        SetDsMac(V, adNextHopExt_f, &dsmac, 0);
        SetDsMac(V, adLengthAdjustType_f, &dsmac, 0);
        SetDsMac(V, adApsBridgeEn_f, &dsmac, 0);
        SetDsMac(V, adCloudSecEn_f, &dsmac, 0);
        /* TsingMa.MX start, all these fields with prefix "ad" do not exist */
        SetDsMac(V, destMap_f, &dsmac, 0);
        SetDsMac(V, nextHopPtr_f, &dsmac, 0);
        SetDsMac(V, nextHopExt_f, &dsmac, 0);
        SetDsMac(V, apsBridgeEn_f, &dsmac, 0);
        /* TsingMa.MX end , must keep clearing fields operation before set dsFwdPtr_f field */
        SetDsMac(V, dsFwdPtr_f, &dsmac, fwd_offset);
        SetDsMac(V, u1Type_f, &dsmac, 0);/* TsingMa.MX */
    }
    else
    {
        uint8 adjust_len_idx = 0;
        if (((GetDsMac(V, nextHopPtrValid_f, &dsmac) == 0) && !DRV_FROM_TMM(lchip))
            || (DRV_FROM_TMM(lchip) && (GetDsMac(V, u1Type_f, &dsmac) != 1)))
        {
            ret = CTC_E_NONE;
            goto out;
        }
        SetDsMac(V, adDestMap_f, &dsmac, p_dsnh_info->dest_map);
        SetDsMac(V, adNextHopPtr_f, &dsmac, p_dsnh_info->dsnh_offset);
        SetDsMac(V, adNextHopExt_f, &dsmac, p_dsnh_info->nexthop_ext);
        SetDsMac(V, adApsBridgeEn_f, &dsmac, p_dsnh_info->aps_en);

        /* TsingMa.MX */
        SetDsMac(V, destMap_f, &dsmac, p_dsnh_info->dest_map);
        SetDsMac(V, nextHopPtr_f, &dsmac, p_dsnh_info->dsnh_offset);
        SetDsMac(V, nextHopExt_f, &dsmac, p_dsnh_info->nexthop_ext);
        SetDsMac(V, apsBridgeEn_f, &dsmac, p_dsnh_info->aps_en);

        if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
        {
            if (0 != p_dsnh_info->adjust_len)
            {
                sys_usw_lkup_adjust_len_index(lchip, p_dsnh_info->adjust_len, &adjust_len_idx);
                SetDsMac(V, adLengthAdjustType_f, &dsmac, adjust_len_idx);
            }
            else
            {
                SetDsMac(V, adLengthAdjustType_f, &dsmac, 0);
            }
        }
        if (DRV_IS_DUET2(lchip) && p_dsnh_info->bypass_igr_edit)
        {
            SetDsMac(V, adNextHopPtr_f, &dsmac, (p_dsnh_info->dsnh_offset | SYS_NH_DSNH_BY_PASS_FLAG));
        }
        else if (DRV_FROM_TM(lchip) && p_dsnh_info->bypass_igr_edit)
        {
            SetDsMac(V, adBypassIngressEdit_f, &dsmac, 1);
            SetDsMac(V, bypassIngressEdit_f, &dsmac, 1);/* TsingMa.MX */
        }

        if (!GetDsMac(V, learnSource_f, &dsmac))
        {
            SetDsMac(V, globalSrcPort_f, &dsmac, SYS_MAP_CTC_GPORT_TO_DRV_GPORT(p_dsnh_info->gport));
        }
        SetDsMac(V, adCloudSecEn_f, &dsmac, p_dsnh_info->cloud_sec_en);
    }

    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_node->ad_idx, cmd, &dsmac);
    
    if (p_node->ad_idx1)
    {
        SetDsMac(V, userDefine_f, &dsmac, 1);
        ret = DRV_IOCTL(lchip, p_node->ad_idx1, cmd, &dsmac);
    }

    out:
    if (p_dsnh_info->need_lock)
    {
        L2_UNLOCK;
    }
    return ret;
}

 int32
sys_usw_l2_update_dsmac(uint8 lchip, void* data, void* change_nh_param)
{
    sys_l2_node_t* p_l2_info = data;
    sys_nh_info_dsnh_t* p_dsnh_info = change_nh_param;
    DsMac_m   dsmac;
    uint32 cmdr  = 0;
    uint32 cmdw  = 0;
    uint32 fwd_offset = 0;
    sys_l2_ad_t         l2_ad ;
    sys_l2_ad_t         l2_ad_old;
    sys_l2_ad_t*        p_ad_get = NULL;
    sys_l2_info_t  new_sys;
    int32 ret = 0;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    sal_memset(&dsmac, 0, sizeof(dsmac));

    /*if true funtion was called because nexthop update,if false funtion was called because using dsfwd*/
    if (p_dsnh_info->need_lock)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Add Lock \n");
        L2_LOCK;
    }

    p_l2_info = ctc_hash_lookup3(pl2_usw_master[lchip]->fdb_hash, &p_dsnh_info->chk_data, p_l2_info, &fwd_offset);
    if (!p_l2_info || p_l2_info->nh_id != p_dsnh_info->nhid)
    {
        ret = CTC_E_NONE;
        goto out;
    }

    sal_memset(&l2_ad, 0, sizeof(l2_ad));

    cmdr = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    cmdw = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_l2_info->adptr->index, cmdr, &dsmac);
    l2_ad_old.index = p_l2_info->adptr->index;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
    if (p_dsnh_info->merge_dsfwd == 2)
    {
        /*update ad from merge dsfwd to using dsfwd*/
        /*1. alloc dsfwd*/
        CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, p_l2_info->nh_id, &fwd_offset, 0, CTC_FEATURE_L2), ret, error0);

        /*2. update ad*/
        SetDsMac(V, nextHopPtrValid_f, &dsmac, 0);
        SetDsMac(V, adDestMap_f, &dsmac, 0);
        SetDsMac(V, adNextHopPtr_f, &dsmac, 0);
        SetDsMac(V, adNextHopExt_f, &dsmac, 0);
        SetDsMac(V, adApsBridgeEn_f, &dsmac, 0);
        SetDsMac(V, adLengthAdjustType_f, &dsmac, 0);
        /* TsingMa.MX start, all these fields with prefix "ad" do not exist */
        SetDsMac(V, destMap_f, &dsmac, 0);
        SetDsMac(V, nextHopPtr_f, &dsmac, 0);
        SetDsMac(V, nextHopExt_f, &dsmac, 0);
        SetDsMac(V, apsBridgeEn_f, &dsmac, 0);
        /* TsingMa.MX end , must keep clearing fields operation before set dsFwdPtr_f field */
        SetDsMac(V, adCloudSecEn_f, &dsmac, 0);
        SetDsMac(V, dsFwdPtr_f, &dsmac, fwd_offset);
        p_l2_info->bind_nh = 0;
        SetDsMac(V, u1Type_f, &dsmac, 0);/* TsingMa.MX */
    }
    else
    {
        uint8 adjust_len_idx = 0;
        if (((GetDsMac(V, nextHopPtrValid_f, &dsmac) == 0) && !DRV_FROM_TMM(lchip))
            || (DRV_FROM_TMM(lchip) && (GetDsMac(V, u1Type_f, &dsmac) != 1)))
        {
            ret = CTC_E_NONE;
            goto out;
        }

        sal_memset(&new_sys, 0, sizeof(sys_l2_info_t));
        new_sys.dsnh_offset = p_dsnh_info->dsnh_offset;
        if (p_dsnh_info->bypass_igr_edit && DRV_IS_DUET2(lchip))
        {
            new_sys.dsnh_offset |= SYS_NH_DSNH_BY_PASS_FLAG;
        }
        SetDsMac(V, adDestMap_f, &dsmac, p_dsnh_info->dest_map);
        SetDsMac(V, adNextHopExt_f, &dsmac, p_dsnh_info->nexthop_ext);
        SetDsMac(V, adNextHopPtr_f, &dsmac, new_sys.dsnh_offset);
        SetDsMac(V, adApsBridgeEn_f, &dsmac, p_dsnh_info->aps_en);
        SetDsMac(V, adBypassIngressEdit_f, &dsmac, p_dsnh_info->bypass_igr_edit);
        if(0 != p_dsnh_info->adjust_len)
        {
            sys_usw_lkup_adjust_len_index(lchip, p_dsnh_info->adjust_len, &adjust_len_idx);
            SetDsMac(V, adLengthAdjustType_f, &dsmac, adjust_len_idx);
        }
        else
        {
            SetDsMac(V, adLengthAdjustType_f, &dsmac, 0);
        }

        /* TsingMa.MX */
        SetDsMac(V, destMap_f, &dsmac, p_dsnh_info->dest_map);
        SetDsMac(V, nextHopExt_f, &dsmac, p_dsnh_info->nexthop_ext);
        SetDsMac(V, nextHopPtr_f, &dsmac, new_sys.dsnh_offset);
        SetDsMac(V, apsBridgeEn_f, &dsmac, p_dsnh_info->aps_en);
        SetDsMac(V, bypassIngressEdit_f, &dsmac, p_dsnh_info->bypass_igr_edit);
        if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
        {
            if (0 != p_dsnh_info->adjust_len)
            {
                sys_usw_lkup_adjust_len_index(lchip, p_dsnh_info->adjust_len, &adjust_len_idx);
                SetDsMac(V, adLengthAdjustType_f, &dsmac, adjust_len_idx);
            }
            else
            {
                SetDsMac(V, adLengthAdjustType_f, &dsmac, 0);
            }
        }

        if (!GetDsMac(V, learnSource_f, &dsmac))
        {
            SetDsMac(V, globalSrcPort_f, &dsmac, SYS_MAP_CTC_GPORT_TO_DRV_GPORT(p_dsnh_info->gport));
        }
        SetDsMac(V, adCloudSecEn_f, &dsmac, p_dsnh_info->cloud_sec_en);
        p_l2_info->bind_nh = (p_dsnh_info->drop_pkt == 0xff)?0:p_l2_info->bind_nh;
    }
    l2_ad.param.ds_mac = &dsmac;
    /*spool ad*/
    CTC_ERROR_GOTO(_sys_usw_l2_dsmac_spool_add(lchip, &l2_ad, &p_ad_get), ret, error0);
    l2_ad.index = p_ad_get->index;
    p_l2_info->adptr = p_ad_get;

    sal_memset(&new_sys, 0, sizeof(sys_l2_info_t));

    new_sys.addr.l2_addr.flag = p_l2_info->flag;
    new_sys.addr.l2_addr.fid = p_l2_info->fid;
    sal_memcpy(&new_sys.addr.l2_addr.mac, &p_l2_info->mac, sizeof(p_l2_info->mac));
    new_sys.addr.l2_addr.gport = p_dsnh_info->gport;
    new_sys.addr_type = SYS_L2_ADDR_TYPE_UC;
    new_sys.ecmp_valid =  p_l2_info->ecmp_valid;
    new_sys.ad_index = p_ad_get->index;
    new_sys.rsv_ad_index = 1;
    new_sys.is_logic_port = GetDsMac(V, learnSource_f, &dsmac);

    DRV_IOCTL(lchip, p_l2_info->adptr->index, cmdw, &dsmac);

    CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &new_sys), ret, error1);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "FDB update_da, ad_offset:0x%x \n", p_l2_info->adptr->index);

    /*Must free old node after write hw*/
    _sys_usw_l2_dsmac_spool_remove(lchip,(void*)&l2_ad_old, &p_ad_get);
out:
    if (p_dsnh_info->need_lock)
    {
        L2_UNLOCK;
    }
    return CTC_E_NONE;

    error1:
    _sys_usw_l2_dsmac_spool_remove(lchip,(void*)&l2_ad, &p_ad_get);
    error0:
    if (p_dsnh_info->need_lock)
    {
        L2_UNLOCK;
    }
    return ret;

}

int32
_sys_usw_l2_bind_nexthop(uint8 lchip, void* p_l2_info, uint8 is_bind, uint8 is_logic, uint32 logic_port)
{
    sys_nh_update_dsnh_param_t update_dsnh;
	int32 ret = 0;
    uint32 hash_idx = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&update_dsnh, 0, sizeof(sys_nh_update_dsnh_param_t));

    if (is_logic)
    {
        sys_l2_vport_2_nhid_t* p_l2_node = (sys_l2_vport_2_nhid_t*)(p_l2_info);
        update_dsnh.data = is_bind?p_l2_info:NULL;
        update_dsnh.updateAd = is_bind?_sys_usw_l2_update_logic_dsmac:NULL;
        update_dsnh.chk_data = is_bind?logic_port:0;
        update_dsnh.bind_feature = is_bind?CTC_FEATURE_L2:0;
        ret = sys_usw_nh_bind_dsfwd_cb(lchip, p_l2_node->nhid, &update_dsnh);
    }
    else
    {
        sys_l2_node_t* p_l2_node = (sys_l2_node_t*)(p_l2_info);
        hash_idx = pl2_usw_master[lchip]->fdb_hash->hash_key(p_l2_node);
        hash_idx = hash_idx%(pl2_usw_master[lchip]->fdb_hash->block_size*pl2_usw_master[lchip]->fdb_hash->block_num);
        update_dsnh.data = is_bind?p_l2_info:NULL;
        update_dsnh.updateAd = is_bind?sys_usw_l2_update_dsmac:NULL;
        update_dsnh.chk_data = is_bind?hash_idx:0;
        update_dsnh.bind_feature = is_bind?CTC_FEATURE_L2:0;
        ret = sys_usw_nh_bind_dsfwd_cb(lchip, p_l2_node->nh_id, &update_dsnh);
        if (CTC_E_NONE == ret)
        {
            p_l2_node->bind_nh = is_bind?1:0;
        }
    }

    return ret;
}

int32
_sys_usw_l2_get_nhid_by_logic_port(uint8 lchip, uint16 logic_port, uint32 *nhp_id)
{
    sys_l2_vport_2_nhid_t *p_node  = NULL;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    SYS_LOGIC_PORT_CHECK(logic_port);

    p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
    if (NULL == p_node)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    else
    {
        *nhp_id = p_node->nhid;
    }

    return CTC_E_NONE;
}

int32
sys_usw_l2_get_nhid_by_logic_port(uint8 lchip, uint16 logic_port, uint32 *nhp_id)
{
    int32 ret = 0;
    L2_LOCK;
    ret = _sys_usw_l2_get_nhid_by_logic_port( lchip, logic_port, nhp_id);
    L2_UNLOCK;
    return ret;
}


/*Notice: here gport means dest port */
STATIC int32
_sys_usw_l2_map_nh_to_sys(uint8 lchip, uint32 nhid, sys_l2_info_t * psys, uint8 is_assign, uint32 gport, uint16 assign_gport_param)
{
    sys_nh_info_dsnh_t nh_info;
    uint8 have_dsfwd = 0;
    uint8 is_discard = 0;
    uint32 assign_gport = assign_gport_param;

    sal_memcpy(&nh_info, &psys->nh_info_dsnh, sizeof(sys_nh_info_dsnh_t));
    is_discard = CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_DISCARD);
    
    have_dsfwd = (nh_info.dsfwd_valid||(nh_info.merge_dsfwd == 2)) &&
        !is_assign &&  !is_discard && (nh_info.nh_entry_type != SYS_NH_TYPE_SRV6);

    if (!have_dsfwd && !nh_info.is_mcast && psys->with_nh && !is_assign)
    {
        psys->bind_nh = is_discard?0:1;
    }
    psys->nhid = nhid;

    /*Due to chip limitation, using dsfwd is not supported for dynamic fdb with no logic port learning*/
    if((have_dsfwd || (nh_info.data && psys->bind_nh)) && !psys->is_logic_port && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_IS_STATIC) && psys->with_nh)
    {
        if(nh_info.nh_entry_type == SYS_NH_TYPE_MCAST || nh_info.nh_entry_type == SYS_NH_TYPE_BRGUC ||
            nh_info.nh_entry_type == SYS_NH_TYPE_DROP || nh_info.nh_entry_type == SYS_NH_TYPE_ILOOP ||
            nh_info.nh_entry_type == SYS_NH_TYPE_TOCPU)
        {
            psys->merge_dsfwd = 1;
        }
        else if(nh_info.nh_entry_type == SYS_NH_TYPE_APS)
        {
            sys_nh_info_dsnh_t nhinfo_tmp;
            sal_memset(&nhinfo_tmp, 0, sizeof(nhinfo_tmp));
            CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, psys->nh_info_dsnh.w_nh_id, &nhinfo_tmp, 0));
            if(nhinfo_tmp.nh_entry_type == SYS_NH_TYPE_BRGUC || nhinfo_tmp.nh_entry_type == SYS_NH_TYPE_ILOOP)
            {
                psys->merge_dsfwd = 1;
            }
            else
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Not support dynamic fdb with nexthop and use dsfwd, because of chip limitation\n");
                return CTC_E_INVALID_PARAM;
            }
        }
        else
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Not support dynamic fdb with nexthop and use dsfwd, because of chip limitation\n");
            return CTC_E_INVALID_PARAM;
        }
    }
    if (!have_dsfwd  && !(nh_info.ecmp_valid || nh_info.is_ecmp_intf))
    {
        psys->merge_dsfwd = 1;
        psys->dsnh_offset = nh_info.dsnh_offset;
        psys->nh_ext = nh_info.nexthop_ext;
        psys->adjust_len = nh_info.adjust_len;
        if (nh_info.bypass_igr_edit && DRV_IS_DUET2(lchip))
        {
            psys->dsnh_offset |= SYS_NH_DSNH_BY_PASS_FLAG;
        }
        psys->by_pass_ingress_edit = nh_info.bypass_igr_edit;
        if (is_assign)
        {
            psys->destmap = SYS_ENCODE_DESTMAP(SYS_MAP_CTC_GPORT_TO_GCHIP(assign_gport), SYS_MAP_CTC_GPORT_TO_DRV_LPORT(assign_gport));
        }
        else
        {
            psys->destmap = nh_info.dest_map;
        }
    }
    else if(nh_info.ecmp_valid)
    {
        psys->destmap = nh_info.ecmp_group_id;
        psys->h_ecmp = nh_info.h_ecmp_en;
    }
    else if(nh_info.is_ecmp_intf)
    {
        psys->merge_dsfwd = 1;
        psys->destmap = nh_info.dest_map;
        psys->dsnh_offset = nh_info.dsnh_offset;
        if (nh_info.bypass_igr_edit && DRV_IS_DUET2(lchip))
        {
            psys->dsnh_offset |= SYS_NH_DSNH_BY_PASS_FLAG;
        }
        psys->by_pass_ingress_edit = nh_info.bypass_igr_edit;
        psys->nh_ext = nh_info.nexthop_ext;
        psys->tunnel_ecmp_high = ((nh_info.ecmp_group_id>>11)&0x1);
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_dsfwd_offset(lchip, nhid, &psys->fwd_ptr, 0, CTC_FEATURE_L2));
        psys->merge_dsfwd = 0;
    }

    psys->ecmp_valid = nh_info.ecmp_valid || nh_info.is_ecmp_intf;
    psys->aps_valid = nh_info.aps_en;
    psys->mc_nh = nh_info.is_mcast;
    psys->cloud_sec_en = nh_info.cloud_sec_en;
    if(is_assign && !psys->is_logic_port)
    {
        psys->addr.l2_addr.gport  = assign_gport;
    }
    else if (psys->is_logic_port && (nh_info.nh_entry_type == SYS_NH_TYPE_OVERLAY || nh_info.bind_ldp))
    {
        psys->addr.l2_addr.gport  = gport? gport : nh_info.logic_port;

        if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) || DRV_IS_TSINGMA(lchip))
        {
            psys->use_lp = 1;
        }

        if (DRV_IS_AT(lchip))
        {
            psys->overlay_nh = 1;
        }

        /*overlay nexthop Not bind nexthop*/
        psys->bind_nh = 0;
    }
    else if (nh_info.nh_entry_type == SYS_NH_TYPE_SRV6)
    {
        psys->bind_nh = 0;
        psys->srv6_nh = 1;
        psys->tunnel_id = nh_info.tunnel_id;
    }
    else
    {
        psys->addr.l2_addr.gport  = gport;
    }

    return CTC_E_NONE;
}
STATIC int32
_sys_usw_l2_get_rchip_reserved_ad(uint8 lchip, uint8 gchip, uint16 lport, uint32* p_ad_idx)
{
    uint32 ad_base = 0;
    uint32 cmd = 0;
    IpeLearningCtl_m lrn_ctl;
    uint8  slice_en = (pl2_usw_master[lchip]->rchip_ad_rsv[gchip] >> 14) & 0x3;
    uint16 rsv_num = pl2_usw_master[lchip]->rchip_ad_rsv[gchip] & 0x3FFF;
    uint32 index = DRV_FROM_AT(lchip)? gchip : 0;
    uint32 fld_id = DRV_FROM_AT(lchip)? FibAccelerationRemoteChipAdBase_remoteChipAdBase_f : (FibAccelerationRemoteChipAdBase_array_0_remoteChipAdBase_f + gchip);

    cmd = DRV_IOR(FibAccelerationRemoteChipAdBase_t, fld_id);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &ad_base));

    cmd = DRV_IOR(IpeLearningCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lrn_ctl));
    ad_base = (ad_base << 6);

    if (GetIpeLearningCtl(V, learningOnStacking_f, &lrn_ctl))
    {
        if (lport >= rsv_num)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        if (slice_en == 0x3)
        {
            rsv_num = rsv_num/SYS_USW_RCHIP_SLICE_NUM;
        }

        if (lport < SYS_USW_RCHIP_SLICE_PORT_NUM)
        {
            if (!(slice_en & 0x1) || (lport >= rsv_num))
            {
                return CTC_E_INVALID_PARAM;
            }
        }
        else
        {
            if (slice_en & 0x1)
            {
                ad_base = ad_base + rsv_num/SYS_USW_RCHIP_SLICE_NUM;
            }

            if (!(slice_en & 0x2) || ((lport-SYS_USW_RCHIP_SLICE_PORT_NUM) >= rsv_num))
            {
                return CTC_E_INVALID_PARAM;
            }
            lport = lport - SYS_USW_RCHIP_SLICE_PORT_NUM;
        }
    }

    *p_ad_idx = ad_base + lport;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_get_reserved_index(uint8 lchip, sys_l2_info_t* psys)
{
    int32  ret              = CTC_E_NONE;
    uint8  is_local_chip    = 0;
    uint8  is_dynamic = 0;
    uint8  is_trunk         = 0;
    uint8  is_phy_port      = 0;
    uint8  is_logic_port    = 0;
    uint8  is_binding       = 0;
    uint32 ad_index         = 0;
    uint8 gchip_id          = 0;
    uint32 nhid             = 0;

    psys->rsv_ad_index = 1;
    gchip_id = CTC_MAP_GPORT_TO_GCHIP(psys->addr.l2_addr.gport);
    is_local_chip = sys_usw_chip_is_local(lchip, gchip_id);
    is_logic_port = psys->is_logic_port;

    /*for cid service id and remote dynamic using, cannot using reserve ad*/
    if ((CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC) && (!is_logic_port && (is_local_chip || 
        CTC_IS_LINKAGG_PORT(psys->addr.l2_addr.gport)))) ||
        (psys->addr.l2_addr.cid && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_PON_EN)) ||
        psys->addr.l2_addr.service_id || (DRV_FROM_AT(lchip) && psys->xdata_en))
    {
         psys->rsv_ad_index = 0;
         return CTC_E_NONE;
    }

    /* is pure dynamic. */
    is_dynamic = (!CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_IS_STATIC) && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_BIND_PORT)\
                    && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_SRC_DISCARD) && !CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_DISCARD));

    is_trunk      = !is_logic_port && CTC_IS_LINKAGG_PORT(psys->addr.l2_addr.gport);
    is_phy_port   = !is_logic_port && !CTC_IS_LINKAGG_PORT(psys->addr.l2_addr.gport);

    if (is_logic_port)
    {
        ret        = _sys_usw_l2_get_nhid_by_logic_port(lchip, psys->addr.l2_addr.gport, &nhid);
        is_binding = !FAIL(ret);
    }

    if (is_dynamic && is_trunk && !psys->with_nh)
    {
        ad_index =  sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK) +
                   CTC_GPORT_LINKAGG_ID(psys->addr.l2_addr.gport); /* linkagg */
    }
    else if (is_dynamic && is_local_chip && is_phy_port && !psys->with_nh)
    {
        ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT) +
                   SYS_MAP_CTC_GPORT_TO_DRV_LPORT(psys->addr.l2_addr.gport); /* gport */
    }
    else if (is_dynamic  && is_logic_port && is_binding)
    {
        if (nhid != psys->nhid)
        {
            return CTC_E_INVALID_CONFIG;
        }
        if (pl2_usw_master[lchip]->vp_alloc_ad_en || CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC))
        {
            sys_l2_vport_2_nhid_t *p_vp_node = NULL;
            p_vp_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, psys->addr.l2_addr.gport);
            if (NULL == p_vp_node)
            {
                return CTC_E_NOT_EXIST;
            }
            if (CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC))
            {
                if (!p_vp_node->ad_idx1)
                {
                    sys_l2_ad_param_t l2_ad_param;
                    sys_l2_ad_t l2_ad;
                    sal_memset(&l2_ad, 0, sizeof(sys_l2_ad_t));
                    sal_memset(&l2_ad_param, 0, sizeof(sys_l2_ad_param_t));
                    l2_ad_param.lchip = lchip;
                    CTC_ERROR_RETURN(_sys_usw_l2_ad_spool_alloc_index(&l2_ad, &l2_ad_param));
                    p_vp_node->ad_idx1 = l2_ad.index;
                    psys->ad_alloc=1;
                }
                psys->rsv_ad_index = 0;
                ad_index = p_vp_node->ad_idx1;
            }
            else
            {
                ad_index = CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC)? p_vp_node->ad_idx1 : p_vp_node->ad_idx;
            }

        }
        else
        {
            ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT) + psys->addr.l2_addr.gport;  /* logic port */
        }

    }
    else if (CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC) && !is_local_chip && is_dynamic && !psys->with_nh && pl2_usw_master[lchip]->rchip_ad_rsv[gchip_id])
    {
        CTC_ERROR_RETURN(_sys_usw_l2_get_rchip_reserved_ad(lchip, gchip_id, CTC_MAP_GPORT_TO_LPORT(psys->addr.l2_addr.gport), &ad_index));
    }
    else
    {
        psys->rsv_ad_index = 0;
    }
    psys->ad_index = ad_index;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_get_reserved_index_by_gport(uint8 lchip,  uint32 gport, uint8 is_logic_port, uint32* ad_index)
{
    uint8 is_local_chip    = 0;
    uint8 is_trunk         = 0;
    uint8 is_phy_port      = 0;
    uint8 gchip_id          = 0;

    gchip_id = CTC_MAP_GPORT_TO_GCHIP(gport);
    is_local_chip = sys_usw_chip_is_local(lchip, gchip_id);
    is_trunk      = !is_logic_port && CTC_IS_LINKAGG_PORT(gport);
    is_phy_port   = !is_logic_port && !CTC_IS_LINKAGG_PORT(gport);

    if(is_phy_port && is_local_chip)
    {
        *ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT) + SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport); /* gport */
    }
    else if(is_trunk)
    {
        *ad_index =  sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK) + CTC_GPORT_LINKAGG_ID(gport); /* linkagg */
    }
    else if (is_logic_port && pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        /*adindex need alloc by sdk. so not have, when write cache*/
        *ad_index = 0;
    }
    else if(is_logic_port)
    {
        *ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT) + gport;  /* logic port */
    }
    else /* for rchip port ad_index*/
    {
        CTC_ERROR_RETURN(_sys_usw_l2_get_rchip_reserved_ad(lchip, gchip_id, CTC_MAP_GPORT_TO_LPORT(gport), ad_index));
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_build_sys_info(uint8 lchip, uint8 type, void * l2, sys_l2_info_t * psys,
                                  uint8 with_nh, uint32 nhid)
{
    uint32 gport = 0;
    uint8 is_cpu_nh = 0;
    uint8 gport_assign = 0;
    uint8 gchip = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(l2);

    if ((L2_TYPE_UC == type) ||(L2_TYPE_TCAM == type))
    {
        ctc_l2_addr_t * l2_addr = (ctc_l2_addr_t *) l2;
        uint16  fid_flag = 0;
        sal_memcpy(&(psys->addr.l2_addr), l2_addr, sizeof(ctc_l2_addr_t));
        gport_assign = (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT))?1:0;
        /*get gchip*/
        sys_usw_get_gchip_id(lchip, &gchip);

        /*get fid flag*/
        fid_flag = _sys_usw_l2_get_fid_flag(lchip, l2_addr->fid);
        psys->is_logic_port = CTC_FLAG_ISSET(fid_flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT);

        psys->with_nh = with_nh;
        
        if (psys->is_logic_port && (!with_nh))
        {
            CTC_ERROR_RETURN(_sys_usw_l2_get_nhid_by_logic_port(lchip, psys->addr.l2_addr.gport, &nhid));
            psys->with_nh = 1;
        }
        if (!psys->with_nh)
        {
            /* if not set discard, get dsfwdptr of port */
            if (!CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_DISCARD))
            {
                uint32 temp_nhid = 0;
                /*get nexthop id from gport*/
                CTC_ERROR_RETURN(sys_usw_l2_get_ucast_nh(lchip, l2_addr->gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC, &temp_nhid));
                CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, temp_nhid, &psys->nh_info_dsnh, 0));
                CTC_ERROR_RETURN(_sys_usw_l2_map_nh_to_sys(lchip, temp_nhid, psys, gport_assign, l2_addr->gport, l2_addr->assign_port));
            }
            else
            {
                psys->fwd_ptr = SYS_FDB_DISCARD_FWD_PTR;
                psys->addr.l2_addr.gport = (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT))? l2_addr->assign_port : DISCARD_PORT;
                psys->merge_dsfwd  = 0;
            }
        }

        else  /* with nexthop */
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nhid, &psys->nh_info_dsnh, 0));
            if (nhid == SYS_NH_RESOLVED_NHID_FOR_TOCPU)
            {
                is_cpu_nh = 1;
            }
            else
            {
                         
                if (psys->nh_info_dsnh.nh_entry_type == SYS_NH_TYPE_MISC)
                {
                    is_cpu_nh = psys->nh_info_dsnh.to_cpu_en;
                }
            }
            
           gport = (psys->is_logic_port || (psys->nh_info_dsnh.nh_entry_type == SYS_NH_TYPE_OVERLAY) || psys->nh_info_dsnh.ecmp_valid || psys->nh_info_dsnh.aps_en || psys->nh_info_dsnh.is_mcast\
                                                            || psys->nh_info_dsnh.is_ecmp_intf)?l2_addr->gport:psys->nh_info_dsnh.gport;
            psys->use_destmap_profile = psys->nh_info_dsnh.use_destmap_profile;
            if (is_cpu_nh && !psys->is_logic_port)
            {
                gport = CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_TO_CPU);
            }
            else if(psys->nh_info_dsnh.drop_pkt && !psys->is_logic_port)
            {
                gport = DISCARD_PORT;
            }
            CTC_ERROR_RETURN(_sys_usw_l2_map_nh_to_sys(lchip, nhid, psys, gport_assign, gport, l2_addr->assign_port));

            /*just for white list entry mismatch src port*/
            if (CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_WHITE_LIST_ENTRY))   /*psys->flag.white_list */
            {
                psys->addr.l2_addr.gport = CTC_MAP_LPORT_TO_GPORT(gchip, SYS_RSV_PORT_DROP_ID);
            }
        }

        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "psys  gport 0x%x\n", psys->addr.l2_addr.gport);

        psys->addr_type = SYS_L2_ADDR_TYPE_UC;
        if(NULL != l2_addr->xdata)
        {
            psys->xdata_en = 1;
            psys->xdata.info = l2_addr->xdata;
        }
    }
    else if (L2_TYPE_MC == type)  /* mc*/
    {
        ctc_l2_mcast_addr_t * l2mc_addr = (ctc_l2_mcast_addr_t *) l2;
        sal_memcpy(&(psys->addr.l2mc_addr), l2mc_addr, sizeof(ctc_l2_mcast_addr_t));
        /* map hw entry */
        CTC_SET_FLAG(psys->addr.l2mc_addr.flag, CTC_L2_FLAG_IS_STATIC);  /*psys->flag.is_static = 1;*/
        psys->addr_type = SYS_L2_ADDR_TYPE_MC;
        psys->share_grp_en = l2mc_addr->share_grp_en;
    }
    else if (L2_TYPE_DF == type)  /*df*/
    {
        ctc_l2dflt_addr_t * l2df_addr = (ctc_l2dflt_addr_t *) l2;
        sal_memcpy(&(psys->addr.l2df_addr), l2df_addr, sizeof(ctc_l2dflt_addr_t));
        /* map hw entry */
         /*CTC_SET_FLAG(psys->flag, CTC_L2_FLAG_IS_STATIC);*/
        psys->addr_type = SYS_L2_ADDR_TYPE_DEFAULT;
        if(NULL != l2df_addr->xdata)
        {
            psys->xdata_en = 1;
            psys->xdata.info = l2df_addr->xdata;
            CTC_ERROR_RETURN(_sys_usw_l2_xdata_check(lchip, psys));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_build_sys_ad_info_by_index(uint8 lchip, uint32 ad_index, sys_l2_info_t* p_sys)
{
    return sys_usw_l2_decode_dsmac(lchip, p_sys, ad_index, NULL);
}

STATIC int32
_sys_usw_l2_map_dma_to_entry(uint8 lchip, uint16 entry_num, void* p_data,
                        ctc_l2_addr_t* pctc, sys_l2_detail_t* pi, uint16* rel_cnt)
{
    uint16 index = 0;
    DmaFibDumpFifo_m* p_dump_info = NULL;
    MsFibAccDmaInfo_m* p_fib_info = NULL;
    uint8* p_cpu_info_dump = NULL;
    CpuInfoDump_m * p_cpu_info_dump_at = NULL;
    hw_mac_addr_t                mac_sa   = { 0 };
    uint32 key_index= 0;
    uint32 ad_index = 0;
    sys_l2_info_t       sys;
    uint16 fid = 0;
    uint16 index1 = 0;
    uint8 xgpon_en = 0;
    uint8  timer = 0;
    uint8 pending = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    *rel_cnt = 0;

    for (index1 = 0; index1 < entry_num; index1++)
    {
        sal_memset(&sys, 0, sizeof(sys_l2_info_t));

        if (DRV_FROM_AT(lchip))
        {
            p_cpu_info_dump_at = (CpuInfoDump_m*)p_data + index1;
            p_fib_info = (MsFibAccDmaInfo_m*)SYS_USW_DMA_GET_INFO_ADDR(lchip, p_cpu_info_dump_at);
        }
        else if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            p_cpu_info_dump = (uint8*)p_data + index1 * sizeof(CpuInfoDump_s);
            p_dump_info = (DmaFibDumpFifo_m*)SYS_USW_DMA_GET_INFO_ADDR(lchip, p_cpu_info_dump);
        }
        else
        {
            p_dump_info = (DmaFibDumpFifo_m*)p_data + index1;
        }

        if (DRV_FROM_AT(lchip))
        {
            fid = GetMsFibAccDmaInfo(V, uShare_gDump_vsiId_f, p_fib_info);

            GetMsFibAccDmaInfo(A, uShare_gDump_mappedMac_f, p_fib_info, mac_sa);
            SYS_USW_SET_USER_MAC(pctc[index].mac, mac_sa);
            key_index = GetMsFibAccDmaInfo(V, uShare_gDump_keyIndex_f, p_fib_info);
            ad_index = GetMsFibAccDmaInfo(V, uShare_gDump_dsAdIndex_f, p_fib_info);
        }
        else
        {
            fid = GetDmaFibDumpFifo(V, vsiId_f, p_dump_info);

            GetDmaFibDumpFifo(A, mappedMac_f, p_dump_info, mac_sa);
            SYS_USW_SET_USER_MAC(pctc[index].mac, mac_sa);
            key_index = GetDmaFibDumpFifo(V, keyIndex_f, p_dump_info);
            ad_index = GetDmaFibDumpFifo(V, dsAdIndex_f, p_dump_info);
        }

        sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if (xgpon_en && DRV_IS_TSINGMA(lchip))
        {
            ad_index = ad_index & 0xDFFFF;
        }
        /*read dsmac */
        sys.xdata.info = pctc[index].xdata;
        _sys_usw_l2_build_sys_ad_info_by_index(lchip, ad_index, &sys);
        CTC_ERROR_RETURN(sys_usw_aging_get_aging_timer(lchip, SYS_AGING_DOMAIN_MAC_HASH, key_index, &timer));
        if(timer == 0)
        {
            if (sys.addr_type == SYS_L2_ADDR_TYPE_MC)
            {
                CTC_SET_FLAG(sys.addr.l2mc_addr.flag, CTC_L2_FLAG_AGING_DISABLE);
            }
            else
            {
                CTC_SET_FLAG(sys.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE);
            }
        }

        pctc[index].fid = fid;
        pctc[index].gport = (sys.addr_type == SYS_L2_ADDR_TYPE_MC) ? 0:(sys.addr.l2_addr.gport);
        pctc[index].flag =  (sys.addr_type == SYS_L2_ADDR_TYPE_MC) ? (sys.addr.l2mc_addr.flag):(sys.addr.l2_addr.flag);

        pctc[index].is_logic_port = SYS_L2_IS_LOGIC_PORT(pctc[index].fid);
        pctc[index].cid = (sys.addr_type == SYS_L2_ADDR_TYPE_MC) ? (sys.addr.l2mc_addr.cid):(sys.addr.l2_addr.cid);
        pctc[index].service_id = sys.addr.l2_addr.service_id;
        pending = DRV_FROM_AT(lchip) ? GetMsFibAccDmaInfo(V, uShare_gDump_pending_f, p_fib_info) : GetDmaFibDumpFifo(V, pending_f, p_dump_info);
        if (pending)
        {
            CTC_SET_FLAG(pctc[index].flag, CTC_L2_FLAG_PENDING_ENTRY);
        }
        if(pi)
        {
            pi[index].ad_index = ad_index;
            pi[index].key_index = key_index;
            pi[index].flag = pctc[index].flag;
            pi[index].pending = pending;
        }

        (*rel_cnt)++;
        index++;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_l2_get_blackhole_entry(uint8 lchip,
                                   ctc_l2_fdb_query_t* pq,
                                   ctc_l2_fdb_query_rst_t* pr,
                                   uint8  only_get_cnt,
                                   sys_l2_detail_t* detail_info)
{
    int32 ret = 0;
    uint32 cmd = 0;
    uint32 max_entry_cnt = pr->buffer_len/sizeof(ctc_l2_addr_t);
    DsFibMacBlackHoleHashKey_m tcam_key;
    sys_l2_detail_t*     temp_detail = detail_info;
    ctc_l2_addr_t*       temp_addr = pr->buffer;
    sys_l2_info_t       l2_info;
    uint32 index = 0;
    uint32 end_index = 0;
    hw_mac_addr_t hw_mac = {0};
    uint16 max_blackhole_entry_num = MCHIP_CAP(SYS_CAP_L2_BLACK_HOLE_ENTRY);
    uint32 ad_index = 0;

    pq->count = 0;
    if (pr->start_index >= max_blackhole_entry_num)
    {
        pr->is_end = 1;
        return CTC_E_NONE;
    }
    if ((pq->query_flag != CTC_L2_FDB_ENTRY_ALL)
        && (pq->query_flag != CTC_L2_FDB_ENTRY_STATIC))
    {
        pr->is_end = 1;
        return CTC_E_NONE;
    }

    end_index = ((pr->start_index + max_entry_cnt) >= max_blackhole_entry_num)
                ? max_blackhole_entry_num : (pr->start_index + max_entry_cnt);

    for (index = pr->start_index; index < end_index; index++)
    {
        sal_memset(&tcam_key, 0, sizeof(tcam_key));
        cmd = DRV_IOR(DsFibMacBlackHoleHashKey_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &tcam_key), ret, error_roll);
        if (!GetDsFibMacBlackHoleHashKey(V, valid_f, &tcam_key))
        {
            continue;
        }
        pq->count++;
        if (only_get_cnt)
        {
            continue;
        }
        temp_addr->fid = DONTCARE_FID;
        GetDsFibMacBlackHoleHashKey(A, mappedMac_f, &tcam_key, hw_mac);
        SYS_USW_SET_USER_MAC(temp_addr->mac, hw_mac);
        ad_index = GetDsFibMacBlackHoleHashKey(V, dsAdIndex_f, &tcam_key);
        /*read dsmac */
        sal_memset(&l2_info, 0, sizeof(l2_info));
        _sys_usw_l2_build_sys_ad_info_by_index(lchip, ad_index, &l2_info);
        temp_addr->gport = (l2_info.addr_type == SYS_L2_ADDR_TYPE_MC) ? 0 : l2_info.addr.l2_addr.gport;
        temp_addr->flag = (l2_info.addr_type == SYS_L2_ADDR_TYPE_MC) ? (l2_info.addr.l2mc_addr.flag):(l2_info.addr.l2_addr.flag);
        if (temp_detail)
        {
            temp_detail->ad_index = ad_index;
            temp_detail->key_index = index;
            temp_detail->flag = temp_addr->flag;
            temp_detail++;
        }
        temp_addr++;
    }
    if (end_index >= max_blackhole_entry_num)
    {
        pr->is_end = 1;
    }
    pr->next_query_index = end_index;
    return CTC_E_NONE;

error_roll:
    pr->next_query_index = index;
    pr->is_end = 1;
    return ret;
}
/* dump all means dump ucast + mcast*/

STATIC int32
_sys_usw_l2_get_pending_fdb_entry_detail(uint8 lchip, ctc_l2_fdb_query_t* query_rq, ctc_l2_fdb_query_rst_t* query_rst, sys_l2_detail_t* detail_info)
{
    hw_mac_addr_t mac_sa = {0};
    uint32 cmd = 0;
    uint32 cmd1 = 0;
    ctc_l2_addr_t* p_buffer = NULL;
    uint32 core_num = drv_vchip_get_core_num(lchip);
    uint32 cache_valid = 0;
    uint32 threshold_cnt = query_rst->buffer_len/sizeof(ctc_l2_addr_t);
    uint32 ad_index = 0;
    uint32 gport = 0;
    uint32 tmp_port = 0;
    uint32 index = 0;
    uint16 fid = 0;
    uint8 core_id = 0;
    uint8 is_logic_port = 0;

    MacLearningCache_m cache_info;

    query_rq->count = 0;

    cmd = DRV_IOR(MacLearningCacheEntryValid_t, MacLearningCacheEntryValid_cacheEntryValid_f);

    for(index = query_rst->start_index; index < 32; index++)
    {
        for(core_id = 0; core_id < core_num; core_id++)
        {
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL((SYS_PP_BASE(lchip) + SYS_CORE_PP_NUM(lchip)*core_id), index, DRV_CMD_PP_EN(cmd), &cache_valid));
            if(!cache_valid)
            {
                if(index == 31 && (core_id == core_num -1))
                {
                    query_rst->is_end = 1;
                }
                continue;
            }
            p_buffer = query_rst->buffer + query_rq->count;

            cmd1 = DRV_IOR(MacLearningCache_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL((SYS_PP_BASE(lchip) + SYS_CORE_PP_NUM(lchip)*core_id), index, DRV_CMD_PP_EN(cmd1), &cache_info));

            fid = GetMacLearningCache(V, vsiId_f, &cache_info);
            is_logic_port = !GetMacLearningCache(V, isGlobalPort_f, &cache_info);
            tmp_port = GetMacLearningCache(V, port_f, &cache_info);
            gport = is_logic_port ? tmp_port : ((tmp_port & 0xff) | (((tmp_port>> 8) & 0x1) << 15) | (((tmp_port >> 9) & 0x7f) << 8));

            GetMacLearningCache(A, mac_f, &cache_info, mac_sa);
            SYS_USW_SET_USER_MAC(p_buffer->mac, mac_sa);
            p_buffer->fid = fid;
            p_buffer->gport = gport;

            CTC_ERROR_RETURN(_sys_usw_l2_get_reserved_index_by_gport(lchip, gport, is_logic_port, &ad_index));

            detail_info[query_rq->count].flag = CTC_L2_FLAG_PENDING_ENTRY;
            detail_info[query_rq->count].ad_index = ad_index;
            /*bit31 means getting agingstatus from MacLearningCacheEntryValid*/
            /*bit30~bit29 means core_id*/
            detail_info[query_rq->count].key_index = index | ((core_id & 0x3) << 29) | (1 << 31);
            detail_info[query_rq->count].pending = 1;

            query_rq->count++;

            if(query_rq->count == threshold_cnt || ((core_id == core_num -1) && ((query_rq->count + core_num) > threshold_cnt)) )
            {
                query_rst->next_query_index = index + 1;
                break;
            }

            if(index == 31 && (core_id == core_num -1))
            {
                query_rst->is_end = 1;
            }
        }

    }
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_get_entry_by_hw_io(uint8 lchip,
                                   ctc_l2_fdb_query_t* query_rq,
                                   ctc_l2_fdb_query_rst_t* query_rst,
                                   uint8  only_get_cnt,
                                   uint8  dump_all,
                                   sys_l2_detail_t* detail_info)
{
    drv_acc_in_t  in;
    drv_acc_out_t out;
    sys_l2_info_t sys_key;
    sys_l2_info_t sys_mac;
    uint32  key_index;
    int32   ret = 0;
    ctc_l2_addr_t* pctc = NULL;
    uint8 is_match = 0;
    uint32 key_cnt = 0;
    uint32 max_index = 0;
    uint32 buf_cnt = query_rst->buffer_len/sizeof(ctc_l2_addr_t);
    uint32 gport_tmp = 0;
    uint32 flag;
    pctc = query_rst->buffer;
    in.type = DRV_ACC_TYPE_LOOKUP;
    in.tbl_id = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.op_type = DRV_ACC_OP_BY_INDEX;
    key_index = query_rst->start_index;

    sys_usw_ftm_query_table_entry_num(lchip, DsFibHost0MacHashKey_t, &max_index);
    max_index += 32;

    do
    {
        if(key_index >= max_index)
        {
            query_rq->count = key_cnt;
            query_rst->is_end = 1;
            return CTC_E_NONE;
        }
        in.index = key_index++;
        if ((ret = sys_usw_chip_check_active(lchip)) < 0 || NULL == pl2_usw_master[lchip])
        {
            return ret;
        }
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
        sal_memset(&sys_key, 0, sizeof(sys_l2_info_t));
        sys_key.key_index = in.index;
        _sys_usw_l2_decode_dskey(lchip, &sys_key, &out.data);
        if (sys_key.key_valid)
        {
            sal_memset(&sys_mac, 0, sizeof(sys_mac));
            sys_mac.xdata.info = only_get_cnt ? NULL : pctc[key_cnt].xdata;
            sys_usw_l2_decode_dsmac(lchip, &sys_mac, sys_key.ad_index, NULL);
            gport_tmp = (sys_mac.addr_type == SYS_L2_ADDR_TYPE_MC) ? 0:(sys_mac.addr.l2_addr.gport);
            flag = (sys_mac.addr_type == SYS_L2_ADDR_TYPE_MC) ? (sys_mac.addr.l2mc_addr.flag):(sys_mac.addr.l2_addr.flag);
            is_match = 0;
            if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_ALL)
            {
                is_match = 1;
            }
            else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_VID)
            {
                if (sys_key.addr.l2_addr.fid == query_rq->fid)
                {
                    is_match = 1;
                }
            }
            else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT)
            {
                if ((gport_tmp == query_rq->gport)
                    && (query_rq->use_logic_port == SYS_L2_IS_LOGIC_PORT(sys_key.addr.l2_addr.fid)))
                {
                    is_match = 1;
                }
            }
            else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN)
            {
                if ((gport_tmp == query_rq->gport)
                    && (query_rq->use_logic_port == sys_mac.is_logic_port)
                    && (sys_key.addr.l2_addr.fid == query_rq->fid))
                {
                    is_match = 1;
                }
            }

            if (query_rq->query_flag == CTC_L2_FDB_ENTRY_STATIC && !CTC_FLAG_ISSET(flag, CTC_L2_FLAG_IS_STATIC))
            {
                is_match = 0;
            }
            else if ((query_rq->query_flag == CTC_L2_FDB_ENTRY_DYNAMIC || query_rq->query_flag == CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC) && CTC_FLAG_ISSET(flag, CTC_L2_FLAG_IS_STATIC))
            {
                is_match = 0;
            }
            else if((query_rq->query_flag != CTC_L2_FDB_ENTRY_MCAST) && (IS_MCAST_MAC_ADDR(sys_key.addr.l2_addr.mac[0])))
            {
                is_match = 0;
            }
            else if((query_rq->query_flag == CTC_L2_FDB_ENTRY_MCAST) && (!IS_MCAST_MAC_ADDR(sys_key.addr.l2_addr.mac[0])))
            {
                is_match = 0;
            }
            else if((query_rq->query_flag == CTC_L2_FDB_ENTRY_PENDING) && !sys_key.pending)
            {
                is_match = 0;
            }
            else if ((CTC_FLAG_ISSET(flag, CTC_L2_FLAG_REMOTE_DYNAMIC) && (query_rq->query_flag == CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC)))
            {
                is_match = 0;
            }
            if (!is_match)
            {
                continue;
            }
            if (!only_get_cnt)
            {
                if(CTC_FLAG_ISSET(sys_key.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE))
                {
                    if (sys_mac.addr_type == SYS_L2_ADDR_TYPE_MC)
                    {
                        CTC_SET_FLAG(sys_mac.addr.l2mc_addr.flag, CTC_L2_FLAG_AGING_DISABLE);
                    }
                    else
                    {
                        CTC_SET_FLAG(sys_mac.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE);
                    }
                }
                sal_memcpy(&pctc[key_cnt].mac, &sys_key.addr.l2_addr.mac, sizeof(mac_addr_t));
                pctc[key_cnt].fid = sys_key.addr.l2_addr.fid;
                pctc[key_cnt].gport = gport_tmp;
                pctc[key_cnt].flag =  flag;

                pctc[key_cnt].is_logic_port = SYS_L2_IS_LOGIC_PORT(pctc[key_cnt].fid);
                pctc[key_cnt].cid = (sys_mac.addr_type == SYS_L2_ADDR_TYPE_MC) ? (sys_mac.addr.l2mc_addr.cid):(sys_mac.addr.l2_addr.cid);
                pctc[key_cnt].service_id = sys_mac.addr.l2_addr.service_id;
                if (sys_key.pending)
                {
                    CTC_SET_FLAG(pctc[key_cnt].flag, CTC_L2_FLAG_PENDING_ENTRY);
                }
                if(detail_info)
                {
                    detail_info[key_cnt].ad_index = sys_key.ad_index;
                    detail_info[key_cnt].key_index = sys_key.key_index;
                    detail_info[key_cnt].flag = pctc[key_cnt].flag;
                    detail_info[key_cnt].pending = sys_key.pending;
                }
            }
            key_cnt ++;
        }
    }while(key_cnt<buf_cnt);

    query_rq->count = key_cnt;
    query_rst->next_query_index = key_index;
    query_rst->is_end = 0;

    return ret;
}

/* dump all means dump ucast + mcast*/
STATIC int32
_sys_usw_l2_get_entry_by_hw(uint8 lchip,
                                   ctc_l2_fdb_query_t* query_rq,
                                   ctc_l2_fdb_query_rst_t* query_rst,
                                   uint8  only_get_cnt,
                                   uint8  dump_all,
                                   sys_l2_detail_t* detail_info)
{
    drv_acc_in_t  in;
    drv_acc_out_t out;
    uint32 max_index = 0;
    uint32 threshold_cnt = query_rst->buffer_len/sizeof(ctc_l2_addr_t);
    void* p_data = NULL;
    uint16 entry_num = 0;
    uint16 rel_cnt = 0;
    DsFibHost0MacHashKey_m fdb_key;
    int32 ret = 0;
    DMA_DUMP_FUN_P p_dma_dump_cb = NULL;
    void* user_data = NULL;
    uint8 is_end = 0;
    ctc_l2_addr_t* p_buffer = NULL;
    dma_dump_cb_parameter_t pa;
    uint8 dma_full_cnt = 0;
    uint8 chan_en = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if ((query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_VID)
        && (query_rq->fid == DONTCARE_FID))
    {
        return _sys_usw_l2_get_blackhole_entry(lchip, query_rq, query_rst, only_get_cnt, detail_info);
    }

    sys_usw_dma_get_chan_en(lchip, SYS_DMA_HASHKEY_CHAN_ID, &chan_en);
    if (!chan_en)
    {
        return _sys_usw_l2_get_entry_by_hw_io(lchip, query_rq, query_rst, only_get_cnt, dump_all, detail_info);
    }

    sal_memset(&in, 0, sizeof(drv_acc_in_t));
    sal_memset(&out, 0, sizeof(drv_acc_out_t));

    sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));

    if (DRV_FROM_TMM(lchip))
    {
        if(threshold_cnt > SYS_L2_FLEX_OP_MAX_NUM)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Query fdb entry number is too big\n");
            return CTC_E_INVALID_PARAM;
        }
        p_data = (void*)mem_malloc(MEM_FDB_MODULE, ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) ? sizeof(CpuInfoDump_s) : sizeof(CpuInfoDump_m))*threshold_cnt);
    }
    else
    {
        p_data = (DmaFibDumpFifo_m*)mem_malloc(MEM_FDB_MODULE, sizeof(DmaFibDumpFifo_m)*threshold_cnt);
    }
    if (p_data == NULL)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;

    }

    /* set request for fib acc to dump hash key by fid */
    SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, query_rq->fid);
    in.type = DRV_FROM_TMM(lchip) ? DRV_ACC_TYPE_DUMP_FLEX  : DRV_ACC_TYPE_DUMP;
    in.tbl_id = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.index = query_rst->start_index;
    in.query_cnt = threshold_cnt;
    in.data = &fdb_key;

    if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_ALL)
    {
        in.op_type = DRV_ACC_OP_BY_ALL;
    }
    else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_VID)
    {
        in.op_type = DRV_ACC_OP_BY_VLAN;
    }
    else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT)
    {
        in.op_type = DRV_ACC_OP_BY_PORT;
    }
    else if (query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN)
    {
        in.op_type = (DRV_ACC_OP_BY_PORT | DRV_ACC_OP_BY_VLAN);
    }
    else if(query_rq->query_type == CTC_L2_FDB_ENTRY_OP_BY_MAC)
    {
        hw_mac_addr_t   hw_mac = {0};
        FDB_SET_HW_MAC(hw_mac, query_rq->mac);
        SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
        in.op_type = DRV_ACC_OP_BY_MAC;
    }
    else
    {
        mem_free(p_data);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if (query_rq->use_logic_port)
    {
        in.gport = query_rq->gport;
        CTC_BIT_SET(in.flag, DRV_ACC_USE_LOGIC_PORT);
    }
    else
    {
        in.gport = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(query_rq->gport);
    }

    CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_UCAST);
    if(dump_all)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_STATIC);
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_MCAST);
    }
    else if (query_rq->query_flag == CTC_L2_FDB_ENTRY_STATIC)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_STATIC);
    }
    else if (query_rq->query_flag == CTC_L2_FDB_ENTRY_DYNAMIC)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
    }
    else if (query_rq->query_flag == CTC_L2_FDB_ENTRY_ALL)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_STATIC);
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
    }
    else if(query_rq->query_type == CTC_L2_FDB_ENTRY_OP_ALL && query_rq->query_flag == CTC_L2_FDB_ENTRY_MCAST)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_STATIC);
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_MCAST);
        CTC_BIT_UNSET(in.flag, DRV_ACC_ENTRY_UCAST);
    }
    else if(query_rq->query_flag == CTC_L2_FDB_ENTRY_PENDING)
    {
        if(query_rq->query_type != CTC_L2_FDB_ENTRY_OP_BY_PORT && query_rq->query_type != CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN)
        {
            CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_STATIC);
            CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
            CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_PENDING);
        }
        if(DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1))
        {
            if(query_rq->query_type != CTC_L2_FDB_ENTRY_OP_ALL)
            {
                mem_free(p_data);
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
                return CTC_E_NOT_SUPPORT;
            }
            L2_DUMP_LOCK;
            ret = _sys_usw_l2_get_pending_fdb_entry_detail(lchip, query_rq, query_rst, detail_info);
            mem_free(p_data);
            L2_DUMP_UNLOCK;
            return ret;
        }
    }
    else if (query_rq->query_flag == CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC)
    {
        CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_LOCAL_DYNAMIC);
    }

    sys_usw_ftm_query_table_entry_num(lchip, DsFibHost0MacHashKey_t, &max_index);
    in.query_end_index = max_index+32;
    if(in.index >= in.query_end_index)
    {
        mem_free(p_data);
        query_rq->count = 0;
        query_rst->is_end = 1;
        return CTC_E_NONE;
    }
    L2_DUMP_LOCK;
    /**/
    CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out),ret, error_proc);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "in.query_cnt:%d, out.query_cnt:%d, out.is_full:%d out.is_end:%d\n", in.query_cnt, out.query_cnt, out.is_full, out.is_end);
    query_rq->count = 0;

    do
    {
        if (out.query_cnt == 0)
        {
            if (out.is_full)
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ACC dump count is 0 and dma is full, dma_full_cnt:%u\n", dma_full_cnt);
                is_end = 0;
                if (dma_full_cnt >= 10)
                {
                    query_rst->is_end = 1;
                    mem_free(p_data);
                    L2_DUMP_UNLOCK;
                    return CTC_E_HW_BUSY;
                }
                dma_full_cnt++;
                in.index = out.key_index;
                CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out),ret, error_proc);
                continue;
            }

            /* Even if count is 0, but Dma memory still may have invalid entry, need clear, Eg:the last invalid entry */
            query_rst->is_end = 1;
            ret = CTC_E_NONE;

            if (DRV_IS_DUET2(lchip))
            {
                ret += sys_usw_dma_wait_desc_done(lchip, SYS_DMA_HASHKEY_CHAN_ID);
                goto error_proc;
            }
            else
            {
                goto error0;
            }
        }

        /* get dump result from dma interface */
        CTC_ERROR_GOTO(sys_usw_dma_get_dump_cb(lchip, (void**)&p_dma_dump_cb, &user_data),ret, error_proc);
        pa.threshold = in.query_cnt;
        pa.entry_count = out.query_cnt;
        pa.fifo_full = out.is_full;
        CTC_ERROR_GOTO((*p_dma_dump_cb)(lchip, &pa, &entry_num, p_data), ret, error_proc);
        rel_cnt = entry_num;
        if (!only_get_cnt)
        {
            p_buffer = query_rst->buffer + query_rq->count;
            _sys_usw_l2_map_dma_to_entry(lchip, entry_num, p_data, p_buffer, detail_info ? (detail_info + query_rq->count) : NULL, &rel_cnt);
        }

        query_rq->count += rel_cnt;

        /* check out status */
        if (out.is_full)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Dma FIFO is Full, continue to dump!\n");
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "          last query end_indesx:0x%x\n", out.key_index);
            is_end = 0;
            in.query_cnt -= entry_num;
            in.index = out.key_index;
            CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out),ret, error_proc);
        }
        else
        {
            if (!out.is_end)
            {
                query_rst->is_end = 0;
                query_rst->next_query_index = out.key_index + 1;
            }
            else
            {
                query_rst->is_end = 1;
            }

            is_end = 1;
        }
    }while(!is_end);

    mem_free(p_data);
    L2_DUMP_UNLOCK;
    return CTC_E_NONE;
error_proc:
    sys_usw_dma_clear_chan_data(lchip, SYS_DMA_HASHKEY_CHAN_ID);

error0:
    mem_free(p_data);
    L2_DUMP_UNLOCK;
    return ret;
}

/**
   @brief Query fdb enery according to specified query condition

 */
STATIC int32
_sys_usw_l2_query_flush_check(uint8 lchip, void* p, uint8 is_flush)
{
    uint8  type           = 0;
    uint16 fid            = 0;
    uint32 gport          = 0;
    uint8  use_logic_port = 0;
    uint8  flag           = 0;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);


    if (is_flush)
    {
        ctc_l2_flush_fdb_t* pf = (ctc_l2_flush_fdb_t *) p;
        type           = pf->flush_type;
        fid            = pf->fid;
        use_logic_port = pf->use_logic_port;
        gport          = pf->gport;
        flag           = pf->flush_flag;
    }
    else
    {
        ctc_l2_fdb_query_t* pq = (ctc_l2_fdb_query_t *) p;
        type           = pq->query_type;
        fid            = pq->fid;
        use_logic_port = pq->use_logic_port;
        gport          = pq->gport;
        flag           = pq->query_flag;
    }
    if ((CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC == flag) && (!DRV_FROM_TMM(lchip)))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if ((CTC_L2_FDB_ENTRY_PENDING == flag || CTC_L2_FDB_ENTRY_MCAST == flag) && CTC_L2_FDB_ENTRY_OP_ALL != type)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if ((type == CTC_L2_FDB_ENTRY_OP_BY_VID) ||
        (type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN) ||
        (type == CTC_L2_FDB_ENTRY_OP_BY_MAC_VLAN))
    {
        SYS_L2UC_FID_CHECK(fid); /* allow 0xFFFF */
    }

    if ((type == CTC_L2_FDB_ENTRY_OP_BY_PORT) ||
        (type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN))
    {
        if (!use_logic_port)
        {
            SYS_GLOBAL_PORT_CHECK(gport);
        }
        else
        {
            SYS_LOGIC_PORT_CHECK(gport);
        }
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_unbind_nhid_by_logic_port(uint8 lchip, uint16 logic_port)
{
    sys_l2_vport_2_nhid_t *p_node;

    uint32 cmd = 0;
    DsMac_m ds_mac;

    p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
    if(p_node)
    {
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID, 1);
        sal_memset(&ds_mac, 0, sizeof(DsMac_m));
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_node->ad_idx, cmd, &ds_mac));
        if (p_node->ad_idx1)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_node->ad_idx1, cmd, &ds_mac));
        }
        if (pl2_usw_master[lchip]->vp_alloc_ad_en)
        {
            sys_usw_ftm_free_table_offset(lchip, DsMac_t, (pl2_usw_master[lchip]->cfg_hw_learn)? 0 : 1, 1, p_node->ad_idx);
        }
        if (p_node->ad_idx1)
        {
            sys_l2_ad_t l2_ad;
            sys_l2_ad_param_t l2_ad_param;
            sal_memset(&l2_ad, 0, sizeof(sys_l2_ad_t));
            sal_memset(&l2_ad_param, 0, sizeof(sys_l2_ad_param_t));
            l2_ad.index = p_node->ad_idx1;
            l2_ad_param.lchip =lchip;
            _sys_usw_l2_ad_spool_free_index(&l2_ad, &l2_ad_param);
        }
        
        _sys_usw_l2_bind_nexthop(lchip, p_node, 0, 1, logic_port);
        ctc_vector_del(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
        mem_free(p_node);
    }
    else
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_l2_bind_nhid_by_logic_port(uint8 lchip, uint16 logic_port, uint32 nhp_id)
{
    sys_l2_info_t          sys;
    sys_l2_vport_2_nhid_t* p_node;
    DsMac_m                ds_mac;
    uint32                 cmd  = 0;
    int32                  ret = 0;
    uint8                  is_new_node = 0;
    uint32                 old_nh_id = 0;
    sys_nh_info_dsnh_t     nh_info;
    uint32 ad_index = 0;


    /*get nhinfo and check*/
    sal_memset(&nh_info, 0, sizeof(sys_nh_info_dsnh_t));
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nhp_id, &nh_info, 0));

    p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID, 1);
    if (NULL == p_node)
    {
        MALLOC_ZERO(MEM_FDB_MODULE, p_node, sizeof(sys_l2_vport_2_nhid_t));
        if (NULL == p_node)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;

        }
        is_new_node = 1;
        if (pl2_usw_master[lchip]->vp_alloc_ad_en)
        {
            if (!pl2_usw_master[lchip]->cfg_hw_learn)
            {
                CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, 1, 1, &ad_index), ret, error_proc);
                p_node->ad_idx = ad_index;
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "alloc ad index:0x%x\n", p_node->ad_idx);
            }
            else
            {
                cmd = DRV_IOR(FibAccelerationCtl_t, FibAccelerationCtl_dsMacBase0_f);
                CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, 0, cmd, &ad_index), ret, error_proc);
                ad_index += logic_port;
                CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 0, 1, ad_index), ret, error_proc);
                p_node->ad_idx = ad_index;
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "alloc ad index:0x%x\n", ad_index);
            }
        }
        else
        {
            p_node->ad_idx = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT) + logic_port;
        }

        p_node->nhid = nhp_id;
        ctc_vector_add(pl2_usw_master[lchip]->vport2nh_vec, logic_port, p_node);
    }
    else
    {
        if (p_node->nhid == nhp_id)
        {
            return CTC_E_NONE;
        }
        old_nh_id = p_node->nhid;
        p_node->nhid = nhp_id;
        p_node->use_ldp = 0;
    }

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    if (SYS_NH_TYPE_OVERLAY == nh_info.nh_entry_type || nh_info.bind_ldp)
    {
         p_node->use_ldp = 1;
        /* use dvp, do nothing*/
    }
    else if (!nh_info.data && !nh_info.dsfwd_valid)
    {
        CTC_ERROR_GOTO(_sys_usw_l2_bind_nexthop(lchip, p_node, 1, 1, logic_port), ret, error_proc);
    }
    else
    {
        CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, nhp_id, &sys.fwd_ptr, 0, CTC_FEATURE_L2), ret, error_proc);
    }

    /* write binding logic-port dsmac */
    sal_memset(&ds_mac, 0, sizeof(DsMac_m));

    sys.is_logic_port = 1;
    sys.addr.l2_addr.gport = logic_port;
    CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, nhp_id, &sys.nh_info_dsnh, 0), ret, error_proc);
    CTC_ERROR_GOTO(_sys_usw_l2_map_nh_to_sys(lchip, nhp_id, &sys, 0, logic_port, 0), ret, error_proc);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Bind nhid by logic port: logic_port:0x%x, merge Dsfwd:%d\n", logic_port, sys.merge_dsfwd);
    CTC_ERROR_GOTO(_sys_usw_l2_encode_dsmac(lchip, &ds_mac, &sys), ret, error_proc);
    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_node->ad_idx, cmd, &ds_mac), ret, error_proc);

    if (p_node->ad_idx1)
    {
        SetDsMac(V, userDefine_f, &ds_mac, 1);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_node->ad_idx1, cmd, &ds_mac), ret, error_proc);
    }

    /*unbind old nexthop*/
    if(!is_new_node && (old_nh_id != nhp_id))
    {
        sys_l2_vport_2_nhid_t  temp_node;
        sal_memset(&temp_node, 0, sizeof(temp_node));
        temp_node.nhid = old_nh_id;
        _sys_usw_l2_bind_nexthop(lchip, &temp_node, 0, 1, logic_port);
    }
    return ret;
   
error_proc:
    if(is_new_node)
    {
        ctc_vector_del(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
        if (pl2_usw_master[lchip]->vp_alloc_ad_en)
        {
            sys_usw_ftm_free_table_offset(lchip, DsMac_t, (pl2_usw_master[lchip]->cfg_hw_learn)?0:1, 1, p_node->ad_idx);
        }

        mem_free(p_node);
    }
    else
    {
        p_node->nhid = old_nh_id;
    }
    return ret;
}

int32
_sys_usw_l2_reset_hw_cb(sys_l2_node_t* p_l2_node, void* user_data)
{
    uint8 lchip = *(uint8*)user_data;
    sys_l2_info_t sys;

    if(p_l2_node)
    {
        sal_memset(&sys, 0, sizeof(sys));
        sys.addr_type = SYS_L2_ADDR_TYPE_UC;
        sys.rsv_ad_index = 1;
        sys.hw_reset = 1;

        sal_memcpy((uint8*)&(sys.addr.l2_addr.mac), (uint8*)&(p_l2_node->mac), sizeof(mac_addr_t));
        sys.addr.l2_addr.fid = p_l2_node->fid;
        sys.addr.l2_addr.flag = p_l2_node->flag;

        sys.ad_index = p_l2_node->adptr->index;
        CTC_ERROR_DUMP(_sys_usw_l2_write_hw(lchip, &sys));
    }

    return CTC_E_NONE;
}


int32 sys_usw_fdb_reset_hw(uint8 lchip, void* p_user_data)
{
    SYS_L2_INIT_CHECK();
    L2_LOCK;
    ctc_hash_traverse(pl2_usw_master[lchip]->fdb_hash, (hash_traversal_fn)_sys_usw_l2_reset_hw_cb, &lchip);
    if (DRV_FROM_TMM(lchip))
    {
        ctc_global_hmac_t hmac;
        sal_memset(&hmac, 0, sizeof(hmac));
        CTC_ERROR_DUMP(sys_usw_global_ctl_get(lchip, CTC_GLOBAL_HMAC_EN, &hmac));
        if (hmac.enable)
        {
            CTC_ERROR_DUMP(sys_usw_global_ctl_set(lchip, CTC_GLOBAL_HMAC_EN, &hmac));
        }
    }
    L2_UNLOCK;

    return CTC_E_NONE;
}

#if 0
int32
sys_usw_l2_fdb_set_policer(uint8 lchip, uint16 logic_port, uint16 policer_id)
{
    uint32 cmd = 0;
    uint32 dsmac_index = 0;
    uint16 policer_ptr = 0;
    DsMac_m dsmac;
    sys_l2_vport_2_nhid_t* p_node;
    sys_qos_policer_param_t policer_param;

    p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, logic_port);
    dsmac_index = p_node->ad_idx;

    sal_memset(&policer_param, 0, sizeof(sys_qos_policer_param_t));
    CTC_ERROR_RETURN(sys_usw_qos_policer_index_get(lchip, policer_id,
                                              SYS_QOS_POLICER_TYPE_FLOW,
                                              &policer_param));

    sal_memset(&dsmac, 0, sizeof(DsMac_t));
    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsmac_index, cmd, &dsmac));

    policer_ptr = policer_param.policer_ptr;
    SetDsMac(V, macDaPolicerEn_f, &dsmac, 1);
    SetDsMac(V, stpCheckDisable_f, &dsmac, (policer_ptr>>12) & 0x1);
    SetDsMac(V, macDaExceptionEn_f, &dsmac, (policer_ptr>>11) & 0x1);
    SetDsMac(V, exceptionSubIndex_f, &dsmac, (policer_ptr>>9) & 0x3);
    SetDsMac(V, categoryIdValid_f, &dsmac, (policer_ptr>>8) & 0x1);
    SetDsMac(V, categoryId_f, &dsmac, (policer_ptr) & 0xFF);

    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsmac_index, cmd, &dsmac));
    return CTC_E_NONE;
}
#endif

#define __FDB_ENTRY__

STATIC int32
_sys_usw_l2_get_fdb_conflict(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr, sys_l2_detail_t* pi)
{
    int32 ret = 0;
    uint8 index = 0;
    uint16 buf_cnt = pr->buffer_len/sizeof(ctc_l2_addr_t);
    uint16 cf_max = 0;
    uint16 cf_count = 0;
    uint32 key_index = 0;
    sys_l2_calc_index_t calc_index;
    sys_l2_detail_t* l2_detail = NULL;
    ctc_l2_addr_t* cf_addr = NULL;
    sys_l2_detail_t* l2_detail_temp = NULL;
    ctc_l2_addr_t* cf_addr_temp = NULL;
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(pq);
    CTC_PTR_VALID_CHECK(pr);
    SYS_L2UC_FID_CHECK(pq->fid);

    if (pq->fid == DONTCARE_FID)
    {
        return CTC_E_NOT_SUPPORT;
    }
    pq->count = 0;
    sal_memset(&calc_index, 0, sizeof(sys_l2_calc_index_t));
    CTC_ERROR_RETURN(_sys_usw_l2_fdb_calc_index(lchip, pq->mac, pq->fid, &calc_index, 0xFF));

    cf_max = calc_index.index_cnt + MCHIP_CAP(SYS_CAP_L2_FDB_CAM_NUM);
    cf_addr = (ctc_l2_addr_t*)mem_malloc(MEM_FDB_MODULE, cf_max * sizeof(ctc_l2_addr_t));
    if (cf_addr == NULL)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(cf_addr, 0, cf_max * sizeof(ctc_l2_addr_t));

    l2_detail = (sys_l2_detail_t*)mem_malloc(MEM_FDB_MODULE, cf_max * sizeof(sys_l2_detail_t));
    if (l2_detail == NULL)
    {
        mem_free(cf_addr);
        return CTC_E_NO_MEMORY;
    }
    sal_memset(l2_detail, 0, cf_max * sizeof(sys_l2_detail_t));
    l2_detail_temp = l2_detail;
    cf_addr_temp = cf_addr;

    for (index = 0; index < cf_max; index++)
    {
        key_index = (index >= calc_index.index_cnt) ? (index - calc_index.index_cnt) : calc_index.key_index[index];
        ret = sys_usw_l2_get_fdb_by_index(lchip, key_index, cf_addr_temp, l2_detail_temp);
        if (ret < 0)
        {
            if (ret == CTC_E_NOT_EXIST)
            {
                ret = CTC_E_NONE;
                continue;
                 /*goto error_return;*/
            }
            else
            {
                goto error_return;
            }
        }
        cf_addr_temp++;
        cf_count++;
        l2_detail_temp++;
    }

    pr->next_query_index = pr->start_index + buf_cnt;
    if (pr->next_query_index >= cf_count)
    {
        pr->next_query_index = cf_count;
        pr->is_end = 1;
    }

    if (pr->start_index >= cf_count)
    {
        goto error_return;
    }
    pq->count = pr->next_query_index - pr->start_index;
    sal_memcpy(pr->buffer, cf_addr + pr->start_index, pq->count * sizeof(ctc_l2_addr_t));

    if (pi)
    {
        sal_memcpy(pi, l2_detail + pr->start_index, pq->count * sizeof(sys_l2_detail_t));
    }

    mem_free(cf_addr);
    mem_free(l2_detail);

    return CTC_E_NONE;

error_return:
    pr->is_end = 1;
    mem_free(cf_addr);
    mem_free(l2_detail);

    return ret;
}

STATIC int32
_sys_usw_hash_reorder_search_free_idx(uint8 lchip, mac_addr_t mac, uint16 fid, uint8 cur_level, uint32* o_idx)
{
    sys_l2_calc_index_t calc_index;
    sys_l2_info_t     sys;
    drv_acc_in_t  in;
    drv_acc_out_t out;
    uint32  key_index;
    uint8   loop;
    uint32  cmd;
    int32   ret = 0;
    FibAccDrainEnable_m fib_acc_drain;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "  mac :%s, fid %u,current level %u\n", sys_output_mac(mac), fid, cur_level);

    sal_memset(&calc_index, 0, sizeof(sys_l2_calc_index_t));
    CTC_ERROR_RETURN(_sys_usw_l2_fdb_calc_index(lchip, mac, fid, &calc_index, cur_level));

    in.type = DRV_ACC_TYPE_LOOKUP;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.op_type = DRV_ACC_OP_BY_INDEX;

    sal_memset(&fib_acc_drain, 0, sizeof(fib_acc_drain));
    cmd = DRV_IOW(FibAccDrainEnable_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_acc_drain));

    *o_idx = 0xFFFFFFFF;
    for (loop = 0; loop < calc_index.index_cnt; loop++)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "    0x%x\n", calc_index.key_index[loop]);
        key_index = calc_index.key_index[loop];
        in.index = key_index ;
        CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out), ret, error_end);

        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        sys.key_index = key_index;
        _sys_usw_l2_decode_dskey(lchip, &sys, &out.data);

        if(!sys.key_valid)
        {
            DsFibHost0MacHashKey_m fdb_key;

            *o_idx = key_index;
            in.type = DRV_ACC_TYPE_ADD;
            in.data = &fdb_key;
            sal_memset(&fdb_key, 0xFF, sizeof(DsFibHost0MacHashKey_m));
            CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out), ret, error_end);
            break;
        }
    }
error_end:
    sal_memset(&fib_acc_drain, 0xFF, sizeof(fib_acc_drain));
    DRV_IOCTL(lchip, 0, cmd, &fib_acc_drain);

    return ret;
}

STATIC int32
_sys_usw_l2_fdb_hra_search(uint8 lchip, sys_l2_hash_reorder_t* pe, uint8 except_level, ctc_linklist_t* p_db)
{
    sys_l2_calc_index_t calc_index;
    sys_l2_hash_reorder_t* p_data = NULL;
    sys_l2_info_t     sys;
    drv_acc_in_t  in;
    drv_acc_out_t out;
    uint32  key_index;
    uint32   out_idx = 0xFFFFFFFF;
    uint32   next = 0;
    sys_l2_hash_reorder_t next_pe;
    uint8      next_level = 0;
    uint8   loop;
    uint8   next_random;
    int32   ret = 0;
    struct ctc_listnode* node;
    sys_l2_hash_reorder_t* tmp_data;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "  mac :%s, fid %u, ad index 0x%x, aging timer %u\n", \
        sys_output_mac(pe->mac), pe->fid, pe->ad_index, pe->aging_timer);

    sal_memset(&next_pe, 0, sizeof(next_pe));
    sal_memset(&calc_index, 0, sizeof(sys_l2_calc_index_t));
    CTC_ERROR_RETURN(_sys_usw_l2_fdb_calc_index(lchip, pe->mac, pe->fid, &calc_index, except_level));

    in.type = DRV_ACC_TYPE_LOOKUP;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.op_type = DRV_ACC_OP_BY_INDEX;

    for(loop=0; loop < calc_index.index_cnt; loop++)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "loop time:%u, index 0x%x\n", loop, calc_index.key_index[loop]);
        key_index = calc_index.key_index[loop];
        in.index = key_index ;
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        sys.key_index = key_index;
        _sys_usw_l2_decode_dskey(lchip, &sys, &out.data);

        CTC_ERROR_GOTO(_sys_usw_hash_reorder_search_free_idx(lchip, sys.addr.l2_addr.mac, sys.addr.l2_addr.fid, \
                                                        calc_index.level[loop], &out_idx), ret, error_0);
        if(0xFFFFFFFF != out_idx)
        {
            next = key_index;
            break;
        }
    }
    /*Not found free postion, select the next search randomly*/
    if(0xFFFFFFFF == out_idx)
    {
        next_random = sal_rand()%calc_index.index_cnt;
        key_index = calc_index.key_index[next_random];
        in.index = key_index ;
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        sys.key_index = key_index;
        _sys_usw_l2_decode_dskey(lchip, &sys, &out.data);

        next = key_index;
        sal_memcpy(&next_pe.mac, &sys.addr.l2_addr.mac, sizeof(mac_addr_t));
        next_pe.fid = sys.addr.l2_addr.fid;
        next_pe.ad_index = sys.ad_index;
        next_pe.aging_timer = sys.pending ? SYS_AGING_TIMER_INDEX_PENDING:(CTC_FLAG_ISSET(sys.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE) ? 0:1);
        sys_usw_aging_get_aging_status(lchip,SYS_AGING_DOMAIN_MAC_HASH , key_index, &next_pe.hit);
        next_level = calc_index.level[next_random];
    }

    /*
     * add current entry to db regressless of whether an free position is found.
     * if you find a free positon, need to add the entry for the target position to db.
     * Eg1. A --> B --> C(free position), need to add A and B to db
     * Eg2. A --> B --> C'(Not a free position), need to add A to db, and use B as the next search entry
    */
    {
        if(p_db->count > pl2_usw_master[lchip]->search_depth)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "move num exceed the max move num, cur move num is %u\n", p_db->count);
            ret =  CTC_E_NO_RESOURCE;
            goto error_0;
        }
        /*check exist in db
          If use hash will be more efficient, but more memory use*/
        for (node = p_db->head; node; CTC_NEXTNODE(node))
        {
            tmp_data = (sys_l2_hash_reorder_t*)CTC_GETDATA(node);
            if(0 == sal_memcmp(tmp_data->mac, &pe->mac, sizeof(mac_addr_t)) && tmp_data->fid == pe->fid)
            {
                ret =  CTC_E_NO_RESOURCE;
                goto error_0;
            }
        }

        p_data = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_hash_reorder_t));
        if(NULL == p_data)
        {
            ret =  CTC_E_NO_RESOURCE;
            goto error_0;
        }
        sal_memcpy(p_data, pe, sizeof(sys_l2_hash_reorder_t));
        p_data->target_idx = next;
        ctc_listnode_add_tail(p_db, p_data);
    }

    if(0xFFFFFFFF == out_idx)
    {
        return _sys_usw_l2_fdb_hra_search(lchip, &next_pe, next_level, p_db);
    }
    else
    {
        p_data = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_hash_reorder_t));
        if(NULL == p_data)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memcpy(&p_data->mac, sys.addr.l2_addr.mac, sizeof(mac_addr_t));
        p_data->fid = sys.addr.l2_addr.fid;
        p_data->ad_index = sys.ad_index;
        p_data->target_idx = out_idx;
        p_data->aging_timer = sys.pending ? SYS_AGING_TIMER_INDEX_PENDING:(CTC_FLAG_ISSET(sys.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE) ? 0:1);
        sys_usw_aging_get_aging_status(lchip,SYS_AGING_DOMAIN_MAC_HASH , out_idx, &p_data->hit);
        ctc_listnode_add_tail(p_db, p_data);
    }

    return 0;
error_0:
    if(out_idx != 0xFFFFFFFF)
    {
        sal_memset(&in, 0, sizeof(in));
        in.tbl_id    = DsFibHost0MacHashKey_t;
        in.module= DRV_ACC_HASH_MODULE_FDB;
        in.op_type = DRV_ACC_OP_BY_INDEX;
        in.type = DRV_ACC_TYPE_DEL;
        in.index = out_idx;
        CTC_ERROR_DUMP(drv_acc_api(lchip, &in, &out));
    }
    return ret;
}

STATIC int32
_sys_usw_l2_fdb_hra_move_hw(uint8 lchip, ctc_linklist_t* p_db)
{
    ctc_listnode_t* node;
    sys_l2_hash_reorder_t* pe;
    drv_acc_in_t  in;
    drv_acc_out_t out;
    DsFibHost0MacHashKey_m fdb_key;
    uint32  hw_mac[2] = {0};

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);

    sal_memset(&in, 0, sizeof(in));
    sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));
    in.type = DRV_ACC_TYPE_ADD;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.op_type = DRV_ACC_OP_BY_INDEX;
    in.data = &fdb_key;
    SetDsFibHost0MacHashKey(V, hashType_f, &fdb_key, 4);

    CTC_LIST_REV_LOOP(p_db, pe, node)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  move mac:%s fid %u, ad_idx %u, target key index 0x%x\n",\
            sys_output_mac(pe->mac), pe->fid, pe->ad_index, pe->target_idx);
        /*For first entry, free target index
          then, add fdb by key normally
        */
        if(p_db->head == node)
        {
            in.type = DRV_ACC_TYPE_DEL;
            in.op_type = DRV_ACC_OP_BY_INDEX;
            in.index = pe->target_idx;
            CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
            break;
        }
        FDB_SET_HW_MAC(hw_mac, pe->mac);
        SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, pe->fid);
        SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
        SetDsFibHost0MacHashKey(V, dsAdIndex_f, &fdb_key, pe->ad_index);
        in.index = pe->target_idx;
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
        CTC_ERROR_RETURN(sys_usw_aging_set_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, in.index, pe->aging_timer, pe->hit));
    }

    return CTC_E_NONE;
}

STATIC void  _sys_usw_l2_fdb_free_node(void* val)
{
    if(val)
    {
        mem_free(val);
    }
    return;
}
STATIC int32
_sys_usw_l2_fdb_hash_reorder_algorithm(uint8 lchip, ctc_l2_addr_t* l2_addr)
{
    int32 ret = 0;
    ctc_linklist_t* p_list = NULL;
    sys_l2_hash_reorder_t tmp_entry;
    sys_l2_calc_index_t   calc_index;
    sys_l2_hash_reorder_t* p_data = NULL;
    drv_acc_in_t in;
    drv_acc_out_t out;
    sys_l2_info_t sys;
    uint32    bmp[2] = {0};
    uint32    out_idx = 0xFFFFFFFF;
    uint8      loop;
    uint8      idx_offset;
    ctc_learning_action_info_t learning_action = {0};
    uint8 old_learning_disable = 0;
    
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);

    sal_memset(&calc_index, 0, sizeof(sys_l2_calc_index_t));
    CTC_ERROR_RETURN(_sys_usw_l2_fdb_calc_index(lchip, l2_addr->mac, l2_addr->fid, &calc_index, 0xFF));
    if(calc_index.index_cnt == SYS_L2_ONE_BLOCK_ENTRY_NUM)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Only have one block, can not do hash reorder\n");
        return CTC_E_HASH_CONFLICT;
    }
    if(NULL == (p_list = ctc_list_create(NULL, _sys_usw_l2_fdb_free_node)))
    {
        return CTC_E_NO_MEMORY;
    }

    in.type = DRV_ACC_TYPE_LOOKUP;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.op_type = DRV_ACC_OP_BY_INDEX;

    /*Now only supports serach once, if you need to support serach multiple times in special scenarios,
      you can quickly support it by modify loop max value,
      loop max value must less than calc_index.index_cnt*/

      /* disable learning */
      sys_usw_learning_get_action(lchip, &learning_action);
      old_learning_disable = learning_action.value;
      if (0 == old_learning_disable)
      {
          learning_action.action = CTC_LEARNING_ACTION_MAC_TABLE_FULL;
          learning_action.value = 1;
          CTC_ERROR_GOTO(sys_usw_learning_set_action(lchip, &learning_action), ret, error_0);
      }
    for(loop=0; loop < 1; loop++)
    {
        while(1)
        {
            idx_offset = sal_rand()%calc_index.index_cnt;
            if(!CTC_BMP_ISSET(bmp, idx_offset))
            {
                CTC_BMP_SET(bmp, idx_offset);
                break;
            }
        }
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "  next key index 0x%x, bit offset is %u\n",calc_index.key_index[idx_offset] ,idx_offset);
        in.index = calc_index.key_index[idx_offset];
        CTC_ERROR_GOTO(drv_acc_api(lchip, &in, &out), ret, error_1);
        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        sys.key_index = calc_index.key_index[idx_offset];
        _sys_usw_l2_decode_dskey(lchip, &sys, &out.data);

        if(NULL == (p_data = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_hash_reorder_t))))
        {
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }
        p_data->target_idx = in.index;
        ctc_listnode_add_tail(p_list, p_data);

        CTC_ERROR_GOTO(_sys_usw_hash_reorder_search_free_idx(lchip, sys.addr.l2_addr.mac, sys.addr.l2_addr.fid, \
                                                        calc_index.level[idx_offset], &out_idx), ret, error_1);
        if(0xFFFFFFFF != out_idx)
        {
            p_data = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_hash_reorder_t));
            if(NULL == p_data)
            {
                ret = CTC_E_NO_MEMORY;
                goto error_1;
            }
            sal_memcpy(&p_data->mac, sys.addr.l2_addr.mac, sizeof(mac_addr_t));
            p_data->fid = sys.addr.l2_addr.fid;
            p_data->ad_index = sys.ad_index;
            p_data->target_idx = out_idx;
            p_data->aging_timer = sys.pending ? SYS_AGING_TIMER_INDEX_PENDING:(CTC_FLAG_ISSET(sys.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE) ? 0:1);
            sys_usw_aging_get_aging_status(lchip,SYS_AGING_DOMAIN_MAC_HASH , out_idx, &p_data->hit);
            ctc_listnode_add_tail(p_list, p_data);
            break;
        }

        sal_memset(&tmp_entry, 0, sizeof(tmp_entry));
        sal_memcpy(&tmp_entry.mac, &sys.addr.l2_addr.mac, sizeof(mac_addr_t));
        tmp_entry.fid = sys.addr.l2_addr.fid;
        tmp_entry.ad_index = sys.ad_index;
        tmp_entry.aging_timer = sys.pending ? SYS_AGING_TIMER_INDEX_PENDING:(CTC_FLAG_ISSET(sys.addr.l2_addr.flag, CTC_L2_FLAG_AGING_DISABLE) ? 0:1);
        ret = _sys_usw_l2_fdb_hra_search(lchip, &tmp_entry, calc_index.level[idx_offset], p_list);

        if(ret == CTC_E_NONE)
        {
            break;
        }
        else if(ret && ret != CTC_E_NO_RESOURCE)
        {
            goto error_1;
        }

        /*clear list node for the next search*/
        ctc_list_delete_all_node(p_list);
    }
    CTC_ERROR_GOTO(_sys_usw_l2_fdb_hra_move_hw(lchip, p_list), ret, error_1);

error_1:
    /* enable learning */
    if (0 == old_learning_disable)
    {
        learning_action.value = 0;
        learning_action.action = CTC_LEARNING_ACTION_MAC_TABLE_FULL;
        CTC_ERROR_DUMP(sys_usw_learning_set_action(lchip, &learning_action));
    }
error_0:
    if(p_list)
    {
        ctc_list_delete(p_list);
    }

    return ret;
}

STATIC int32
_sys_usw_l2_get_fdb_entry_detail_by_mac_vlan(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr, sys_l2_detail_t* p_detail)
{
    mac_lookup_result_t     rslt ;
    sys_l2_info_t           sys ;
    int32  ret = CTC_E_NONE;
    uint32  key_index = 0;
    uint32  ad_index = 0;

    sal_memset(&rslt, 0, sizeof(mac_lookup_result_t));
    sal_memset(&sys, 0,sizeof(sys));
    if(pq->fid == DONTCARE_FID)
    {
        if(!_sys_usw_l2_black_hole_lookup(lchip, pq->mac, &key_index, &ad_index))
        {
            ad_index = 0XFFFFFFFF;
        }
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, pq->mac, pq->fid, &rslt));
        if (rslt.pending)
        {
            CTC_SET_FLAG(sys.addr.l2_addr.flag, CTC_L2_FLAG_PENDING_ENTRY);
            if (pr->buffer_len)
            {
                CTC_SET_FLAG(pr->buffer->flag, CTC_L2_FLAG_PENDING_ENTRY);
            }
        }
        if(rslt.hit)
        {
            key_index = rslt.key_index;
            ad_index = rslt.ad_index;
        }
        else
        {
            ad_index = 0xFFFFFFFF;
        }
    }

    if(ad_index != 0xFFFFFFFF)
    {
        uint32* p_flag = NULL;
        uint8   timer = 0;
        sal_memset(&sys, 0, sizeof(sys_l2_info_t));

        sys.g_xdata_info = (p_detail == NULL) ? 0 : 1;
        sys.xdata.info = pr->buffer->xdata;
        ret = _sys_usw_l2_build_sys_ad_info_by_index(lchip, ad_index, &sys);
        p_flag = (sys.addr_type == SYS_L2_ADDR_TYPE_MC) ? &sys.addr.l2mc_addr.flag : &sys.addr.l2_addr.flag;
        CTC_ERROR_RETURN(sys_usw_aging_get_aging_timer(lchip, SYS_AGING_DOMAIN_MAC_HASH, key_index, &timer));
        if(timer == 0)
        {
            CTC_SET_FLAG((*p_flag), CTC_L2_FLAG_AGING_DISABLE);
        }

        /*check flag*/
        if( (CTC_L2_FDB_ENTRY_STATIC == pq->query_flag && !CTC_FLAG_ISSET((*p_flag), CTC_L2_FLAG_IS_STATIC) )||
             (CTC_L2_FDB_ENTRY_DYNAMIC == pq->query_flag && CTC_FLAG_ISSET((*p_flag), CTC_L2_FLAG_IS_STATIC)))
        {
            goto end;
        }

        /*key*/
        sal_memcpy(&sys.addr.l2_addr.mac, &pq->mac, sizeof(mac_addr_t));
        sys.addr.l2_addr.fid = pq->fid;
        sys.addr.l2_addr.xdata = sys.xdata.info;

        if(pr->buffer_len)
        {
            sal_memcpy((uint8*)pr->buffer, (uint8*)&sys.addr.l2_addr, sizeof(ctc_l2_addr_t));
            pq->count = 1;
            if(SYS_L2_ADDR_TYPE_MC == sys.addr_type)
            {
                pr->buffer->cid = sys.addr.l2mc_addr.cid;
                pr->buffer->flag = sys.addr.l2mc_addr.flag;
            }
        }
        else
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "No buffer for get fdb entry!!!!!!!!!!!!!!!!\n");
        }


        if(p_detail)
        {
            p_detail->ad_index = ad_index;
            p_detail->key_index = key_index;
            p_detail->pending = rslt.pending;
            p_detail->flag = (sys.addr_type == SYS_L2_ADDR_TYPE_MC ? sys.addr.l2mc_addr.flag : sys.addr.l2_addr.flag);

        }
    }

end:
    pr->is_end = 1;
    return ret;
}

STATIC int32
_sys_usw_l2_get_fdb_entry_detail_by_mac(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr, sys_l2_detail_t* p_detail)
{
    ctc_l2_fdb_query_t      temp_query ;
    ctc_l2_fdb_query_rst_t  temp_query_rst;
    sys_l2_detail_t*        temp_detail = NULL;
    uint32 max_entry_cnt = 0;
    uint32 loop = 0;
    int32  ret = CTC_E_NONE;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memcpy(&temp_query, pq, sizeof(temp_query));
    sal_memcpy(&temp_query_rst, pr, sizeof(temp_query_rst));

    max_entry_cnt = pr->buffer_len/sizeof(ctc_l2_addr_t);
    temp_detail = (sys_l2_detail_t*)mem_malloc(MEM_FDB_MODULE, DUMP_MAX_ENTRY*sizeof(sys_l2_detail_t));
    if(!temp_detail)
    {
        ret = CTC_E_NO_MEMORY;
        goto error0;
    }

    temp_query.query_type = CTC_L2_FDB_ENTRY_OP_ALL;
    temp_query_rst.buffer = (ctc_l2_addr_t*)mem_malloc(MEM_FDB_MODULE, DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t));
    if(!temp_query_rst.buffer)
    {
        ret = CTC_E_NO_MEMORY;
        goto error1;
    }
    sal_memset(temp_query_rst.buffer, 0, DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t));
    temp_query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
    temp_query_rst.next_query_index = pr->start_index;

    do
    {
        temp_query_rst.start_index = temp_query_rst.next_query_index;
        CTC_ERROR_GOTO(_sys_usw_l2_get_entry_by_hw(lchip, &temp_query, &temp_query_rst, 0, 0, temp_detail), ret ,error2);
        pr->is_end = temp_query_rst.is_end;

        for(loop=0; loop<temp_query.count && pq->count<max_entry_cnt;loop++)
        {
            if(sal_memcmp(&pq->mac, &(temp_query_rst.buffer+loop)->mac, sizeof(mac_addr_t)))
            {
                continue;
            }
            sal_memcpy((uint8*)((ctc_l2_addr_t*)pr->buffer+pq->count), (uint8*)((ctc_l2_addr_t*)temp_query_rst.buffer+loop), sizeof(ctc_l2_addr_t));
            if(p_detail)
            {
                sal_memcpy((uint8*)(p_detail+pq->count), (uint8*)(temp_detail+loop), sizeof(sys_l2_detail_t));
            }
            pq->count++;

        }

        /*The user's buffer is full but there are entries in hardware table*/
        if(pq->count == max_entry_cnt && loop < temp_query.count)
        {
			pr->next_query_index = (temp_detail+loop)->key_index;
            pr->is_end = 0;
            break;
        }

    }while(!temp_query_rst.is_end);

error2:
    mem_free(temp_query_rst.buffer);
error1:
    mem_free(temp_detail);
error0:
    return ret;
}

STATIC int32
_sys_usw_l2_get_fdb_entry_detail(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr, sys_l2_detail_t* p_detail)
{
    int32 ret = CTC_E_NONE;
    uint32 sw_get_cnt = 0;
    #if defined(DUET2)
    uint8  is_sw_multi = 0;
    #endif
    ctc_l2_addr_t* p_user_buf_old = NULL;
    uint32  user_buf_len_old = 0;
    sys_l2_detail_t* p_temp_detail = NULL;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if((pq->query_flag == CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC) && (!DRV_FROM_TMM(lchip)))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        ret =  CTC_E_NOT_SUPPORT;
        goto done;

    }
    if ((pq->query_type != CTC_L2_FDB_ENTRY_OP_BY_MAC_VLAN)
        && (pq->query_flag == CTC_L2_FDB_ENTRY_CONFLICT))
    {
        ret =  CTC_E_NOT_SUPPORT;
        goto done;
    }

    if(!DRV_FROM_TMM(lchip) && pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_MAC)
    {
        ret = _sys_usw_l2_get_fdb_entry_detail_by_mac(lchip, pq, pr, p_detail);
        goto done;

    }
    else if(pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_MAC_VLAN)
    {
        if (pq->query_flag == CTC_L2_FDB_ENTRY_CONFLICT)
        {
            ret = _sys_usw_l2_get_fdb_conflict(lchip, pq, pr, p_detail);
            goto done;
        }
        else
        {
            ret = _sys_usw_l2_get_fdb_entry_detail_by_mac_vlan(lchip, pq, pr, p_detail);
            goto done;
        }
    }
    else
    {
        p_user_buf_old = pr->buffer;
        user_buf_len_old = pr->buffer_len;
        /*get software*/
        #if defined(DUET2)
            if (DRV_IS_DUET2(lchip) &&
                ((pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_VID) || (pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT) || (pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN))
                &&((pr->start_index == 0) || (0 != is_sw_multi)))
            {
                uint32 hash_node_id = 0;
                uint32 list_node_id = 0;
                sys_l2_destmap_profile_fdb_t user_data;

                /*transfer info from pr->start_index*/
                FDB_MAC_FID_SW_QUERY_IDX_DECODE(pr->start_index, is_sw_multi, hash_node_id, list_node_id);
                pq->count = 0;
                user_data.lchip = lchip;
                user_data.pq = pq;
                user_data.pr = pr;
                user_data.p_detail = p_detail;
                ctc_hash_traverse3(pl2_usw_master[lchip]->fdb_hash, (hash_traversal_3_fn)_sys_usw_l2_get_dstmp_profile_cb, &user_data, hash_node_id, list_node_id);
                sw_get_cnt = pq->count;
            }
        #endif

        /*get hardware*/
        if (pr->buffer_len >= sizeof(ctc_l2_addr_t))
        {
            pq->count = 0;
            #if defined(DUET2)
            pr->start_index = is_sw_multi ? 0 : pr->start_index ;
            #endif
            p_temp_detail = p_detail ? p_detail + sw_get_cnt : p_detail;
            ret =  _sys_usw_l2_get_entry_by_hw(lchip, pq, pr, 0, 0, p_temp_detail);
            pq->count += sw_get_cnt;
        }
        pr->buffer = p_user_buf_old;
        pr->buffer_len = user_buf_len_old;
    }

done:
    return ret;
}


/* call back funtion fot trie sort*/
STATIC int32
sys_usw_l2_get_fdb_entry_cb(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr)
{
    CTC_PTR_VALID_CHECK(pq);
    CTC_PTR_VALID_CHECK(pr);

    pq->query_type = CTC_L2_FDB_ENTRY_OP_ALL;
    pq->query_flag = CTC_L2_FDB_ENTRY_ALL;

    return _sys_usw_l2_get_entry_by_hw(lchip, pq, pr, 0,1, NULL);
}

int32
sys_usw_l2_get_fdb_entry(uint8 lchip, ctc_l2_fdb_query_t* pq,
                                ctc_l2_fdb_query_rst_t* pr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(pq);
    CTC_PTR_VALID_CHECK(pr);

    CTC_ERROR_RETURN(_sys_usw_l2_query_flush_check(lchip, pq, 0));

    pq->count = 0;
    pr->next_query_index = 0;
    pr->is_end = 0;
    return _sys_usw_l2_get_fdb_entry_detail(lchip, pq, pr, NULL);
}

#define _FDB_COUNT_
/**
 * get some type fdb count by specified port,not include the default entry num
 */

#define GET_STATIC_ENTRY_CNT \
do{ \
    query.query_flag = CTC_L2_FDB_ENTRY_STATIC;\
    query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);\
    query_rst.next_query_index = 0;\
    do\
    {\
        query_rst.start_index = query_rst.next_query_index;\
        CTC_ERROR_RETURN(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 1, 0, NULL));\
        static_entry_cnt += query.count;\
    }while(!query_rst.is_end);\
}while(0)

STATIC int32
_sys_usw_l2_get_count_by_port(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    ctc_l2_fdb_query_rst_t   query_rst ;
    ctc_l2_fdb_query_t   query  ;
    uint32   mac_limit_cnt = 0;
    uint32   static_entry_cnt = 0;
    drv_acc_in_t in;
    drv_acc_out_t out;
    uint8   gchip = 0;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memcpy(&query, pq, sizeof(query));
    sal_memset(&query_rst, 0, sizeof(query_rst));

    gchip = CTC_MAP_GPORT_TO_GCHIP(pq->gport);
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));

    /*use logic port or !local chip*/
    if (pq->use_logic_port || (gchip != (CTC_MAP_GPORT_TO_GCHIP(pq->gport))) || pq->query_flag == CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC)
    {
        query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
        query_rst.next_query_index = 0;
        do
        {
            query_rst.start_index = query_rst.next_query_index;
            CTC_ERROR_RETURN(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 1, 0, NULL));
            pq->count += query.count;
        }while(!query_rst.is_end);

        return CTC_E_NONE;
    }

    sal_memset(&in, 0, sizeof(in));
    sal_memset(&out, 0, sizeof(out));

    in.tbl_id = DsMacLimitCount_t;
    in.module= DRV_ACC_HASH_MODULE_MAC_LIMIT;
    in.type = DRV_ACC_TYPE_LOOKUP;
    in.op_type = DRV_ACC_OP_BY_PORT;
    in.gport = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(pq->gport);
    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
    mac_limit_cnt = out.query_cnt;

    switch (pq->query_flag)
    {
    case CTC_L2_FDB_ENTRY_STATIC:
        GET_STATIC_ENTRY_CNT;
        pq->count = static_entry_cnt;
        break;

    case  CTC_L2_FDB_ENTRY_DYNAMIC:
        if (pl2_usw_master[lchip]->static_fdb_limit)
        {
            GET_STATIC_ENTRY_CNT;
        }

        pq->count = mac_limit_cnt - static_entry_cnt;
        break;
    case CTC_L2_FDB_ENTRY_ALL:
        if (!pl2_usw_master[lchip]->static_fdb_limit)
        {
            GET_STATIC_ENTRY_CNT;
        }
        pq->count = mac_limit_cnt + static_entry_cnt;
        break;
    default:
        break;
    }

    return CTC_E_NONE;
}



/**
 * get some type fdb count by specified vid,not include the default entry num
 */
STATIC int32
_sys_usw_l2_get_count_by_fid(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    ctc_l2_fdb_query_rst_t   query_rst ;
    ctc_l2_fdb_query_t   query ;
    uint32   mac_limit_cnt = 0;
    uint32   static_entry_cnt = 0;


    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);


    sal_memcpy(&query, pq, sizeof(query));
    sal_memset(&query_rst, 0, sizeof(query_rst));



    if((pq->fid <= CTC_MAX_VLAN_ID) && (CTC_L2_FDB_ENTRY_STATIC != pq->query_flag)&& (CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC != pq->query_flag))
    {
        drv_acc_in_t in;
        drv_acc_out_t out;
        sal_memset(&in, 0, sizeof(in));
        sal_memset(&out, 0, sizeof(out));

        in.tbl_id = DsMacLimitCount_t;
        in.module= DRV_ACC_HASH_MODULE_MAC_LIMIT;
        in.type = DRV_ACC_TYPE_LOOKUP;
        in.op_type = DRV_ACC_OP_BY_VLAN;
        in.data = &(pq->fid);
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
        mac_limit_cnt = out.query_cnt;

        switch (pq->query_flag)
        {
        case  CTC_L2_FDB_ENTRY_DYNAMIC:
            if (pl2_usw_master[lchip]->static_fdb_limit)
            {
                GET_STATIC_ENTRY_CNT;
            }

            pq->count = mac_limit_cnt - static_entry_cnt;
            break;

        case CTC_L2_FDB_ENTRY_ALL:
            if (!pl2_usw_master[lchip]->static_fdb_limit)
            {
                GET_STATIC_ENTRY_CNT;
            }
            pq->count = mac_limit_cnt + static_entry_cnt;

        default:
            break;
        }

    }
    else
    {
        sal_memcpy(&query, pq, sizeof(query));

        query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
        query_rst.next_query_index = 0;
        do
        {
            query_rst.start_index = query_rst.next_query_index;
            CTC_ERROR_RETURN(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 1, 0, NULL));
            pq->count += query.count;
        }while(!query_rst.is_end);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_get_count_by_port_fid(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    ctc_l2_fdb_query_rst_t   query_rst ;
    ctc_l2_fdb_query_t   query;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memcpy(&query, pq, sizeof(query));
    sal_memset(&query_rst, 0, sizeof(query_rst));
    query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
    query_rst.next_query_index = 0;
    do
    {
        query_rst.start_index = query_rst.next_query_index;
        CTC_ERROR_RETURN(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 1, 0, NULL));
        pq->count += query.count;
    }while(!query_rst.is_end);

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_l2_get_count_by_mac(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    int32 ret = CTC_E_NONE;
    uint32 loop = 0;
    ctc_l2_fdb_query_rst_t   query_rst;
    ctc_l2_fdb_query_t       query;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memcpy(&query, pq, sizeof(query));
    sal_memset(&query_rst, 0, sizeof(query_rst));

    query.query_type = DRV_FROM_TMM(lchip) ? CTC_L2_FDB_ENTRY_OP_BY_MAC : CTC_L2_FDB_ENTRY_OP_ALL;
    query_rst.buffer = (ctc_l2_addr_t*)mem_malloc(MEM_FDB_MODULE, DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t));
    if (NULL == query_rst.buffer)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " no memory \n ");
        return CTC_E_NO_MEMORY;
    }
    query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
    query_rst.next_query_index = 0;
    do
    {
        query_rst.start_index = query_rst.next_query_index;
        CTC_ERROR_GOTO(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 0, -0, NULL),ret, error_proc);
        if(DRV_FROM_TMM(lchip))
        {
            pq->count += query.count;
        }
        else
        {
            for(loop=0; loop<query.count;loop++)
            {
                if(!sal_memcmp(&pq->mac, &(query_rst.buffer+loop)->mac, sizeof(mac_addr_t)))
                {
                    pq->count++;
                }
            }
        }
    }while(!query_rst.is_end);

error_proc:
    mem_free(query_rst.buffer);
    return ret;

}


/**
   @brief only count unicast FDB entries
 */
STATIC int32
_sys_usw_l2_get_count_by_all(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    ctc_l2_fdb_query_rst_t   query_rst;
    ctc_l2_fdb_query_t   query;
    uint32   static_entry_cnt = 0;
    drv_acc_in_t  in;
    drv_acc_out_t out;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memcpy(&query, pq, sizeof(query));
    sal_memset(&query_rst, 0, sizeof(query_rst));

    sal_memset(&in,0,sizeof(drv_acc_in_t));
    sal_memset(&out,0,sizeof(drv_acc_out_t));

    in.tbl_id = DsMacLimitCount_t;
    in.module= DRV_ACC_HASH_MODULE_MAC_LIMIT;
    in.type = DRV_ACC_TYPE_LOOKUP;
    in.op_type = DRV_ACC_OP_BY_ALL;

    switch (pq->query_flag)
    {
    case CTC_L2_FDB_ENTRY_STATIC:
        GET_STATIC_ENTRY_CNT;
        pq->count = static_entry_cnt;
        break;

    case  CTC_L2_FDB_ENTRY_DYNAMIC:
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

        pq->count = out.query_cnt;
        break;
    case CTC_L2_FDB_ENTRY_ALL:
        CTC_BIT_SET(in.flag, DRV_ACC_STATIC_MAC_LIMIT_CNT);
        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

        pq->count = out.query_cnt;
        break;
    case CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC:
        sal_memcpy(&query, pq, sizeof(query));

        query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);
        query_rst.next_query_index = 0;
        do
        {
            query_rst.start_index = query_rst.next_query_index;
            CTC_ERROR_RETURN(_sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 1, 0, NULL));
            pq->count += query.count;
        }
        while (!query_rst.is_end);
        break;
        
    default:
        break;
    }

    return CTC_E_NONE;
}

/**
 * get some type fdb count, not include the default entry num
 */
int32
sys_usw_l2_get_fdb_count(uint8 lchip, ctc_l2_fdb_query_t* pq)
{
    mac_lookup_result_t rslt;
    sys_l2_info_t sys;
    uint32        flag = 0;
    
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(pq);
    CTC_MAX_VALUE_CHECK(pq->query_flag, MAX_CTC_L2_FDB_ENTRY_OP - 1);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_ERROR_RETURN(_sys_usw_l2_query_flush_check(lchip, pq, 0));

    pq->count = 0;

    switch (pq->query_type)
    {
    case CTC_L2_FDB_ENTRY_OP_BY_VID:

        return _sys_usw_l2_get_count_by_fid(lchip, pq);

    case CTC_L2_FDB_ENTRY_OP_BY_PORT:
        return _sys_usw_l2_get_count_by_port(lchip, pq);

    case CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN:
        return _sys_usw_l2_get_count_by_port_fid(lchip, pq);
    case CTC_L2_FDB_ENTRY_OP_BY_MAC:
        return _sys_usw_l2_get_count_by_mac(lchip, pq);
    case CTC_L2_FDB_ENTRY_OP_ALL:
        return _sys_usw_l2_get_count_by_all(lchip, pq);
        break;

    case CTC_L2_FDB_ENTRY_OP_BY_MAC_VLAN:
        CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, pq->mac, pq->fid, &rslt));
        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        _sys_usw_l2_build_sys_ad_info_by_index(lchip, rslt.ad_index, &sys);
        flag = (sys.addr_type == SYS_L2_ADDR_TYPE_UC) ? sys.addr.l2_addr.flag : sys.addr.l2mc_addr.flag;
        RETURN_IF_FLAG_NOT_MATCH(pq->query_flag, flag);
        pq->count = (rslt.hit);

        break;

    default:
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    return CTC_E_NONE;
}

#define __SPOOL__
/* share pool for uc only. and us distinguished by fwdptr */
uint32
_sys_usw_l2_ad_spool_hash_make(sys_l2_ad_t* p_ad)
{
    return ctc_hash_caculate(TABLE_ENTRY_SIZE(p_ad->param.lchip, DsMac_t), p_ad->param.ds_mac);
}

#define SYS_FDB_AD_SPOOL_INVALID_IDX          0xFFFFFF

int32
_sys_usw_l2_ad_spool_hash_cmp(sys_l2_ad_t* p_ad1, sys_l2_ad_t* p_ad2)
{
    uint32 cmd = 0;
    DsMac_m ds_mac;
    uint8 lchip = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (!p_ad1 || !p_ad2)
    {
        return FALSE;
    }
    if (SYS_FDB_AD_SPOOL_INVALID_IDX == p_ad1->index)  /*for spool add error rollback*/
    {
        return TRUE;
    }

    lchip = p_ad2->param.lchip;
    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    if(DRV_IOCTL(lchip, p_ad1->index, cmd, &ds_mac) < 0)
    {
        return FALSE;
    }
    if (!sal_memcmp(&ds_mac, p_ad2->param.ds_mac, TABLE_ENTRY_SIZE(lchip, DsMac_t)))
    {
        return TRUE;
    }

    return FALSE;
}

int32
_sys_usw_l2_ad_spool_alloc_index(sys_l2_ad_t* p_ad, void* user_data)
{
    sys_l2_ad_update_node_t* p_ad_node;
    uint32 ad_index = 0;
    int32 ret = 0;
    uint32 ldp = ((sys_l2_ad_param_t*)user_data)->ldp;
    uint32 srv6_nhid = ((sys_l2_ad_param_t*)user_data)->srv6_nhid;
    uint8  lchip = ((sys_l2_ad_param_t*)user_data)->lchip;
    
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if(!(CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        ret = sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, 1, 1, &ad_index);
        if(ret)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "spool alloc index failed,  line=%d\n",__LINE__);
            p_ad->index = SYS_FDB_AD_SPOOL_INVALID_IDX;     /*spool alloc index failed, return invalid ad_index*/
            return -1;
        }
        p_ad->index = ad_index;
    }
    else
    {
        ret = sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 1, 1, p_ad->index);
    }

    if(!ldp && (0 == srv6_nhid))
    {
        return CTC_E_NONE;
    }
    /*overlay update ldp, build another node*/
    if(NULL == (p_ad_node = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_ad_update_node_t))))
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_ad_node, 0, sizeof(sys_l2_ad_update_node_t));
    p_ad_node->ad_index = p_ad->index;
    p_ad_node->ldp = ldp;
    p_ad_node->srv6_nhid = srv6_nhid;
    if(NULL == ctc_hash_insert(pl2_usw_master[lchip]->ad_hash, p_ad_node))
    {
        return CTC_E_NO_MEMORY;
    }

    if (ldp)
    {
        p_ad->ldp_en = 1;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add l2 dsmac %d to ldp %d\n", p_ad->index, p_ad_node->ldp);
        sys_usw_add_ldp_node(lchip, pl2_usw_master[lchip]->ldp_hash, p_ad_node->ldp, &p_ad_node->head);
    }

    if (p_ad_node->srv6_nhid)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add l2 dsmac %d to nhid %d\n", p_ad->index , p_ad_node->srv6_nhid);
        sys_usw_add_ldp_node(lchip, pl2_usw_master[lchip]->nhid_hash, p_ad_node->srv6_nhid, &p_ad_node->nhid_list_head);
    }
    return ret;
}

int32
_sys_usw_l2_ad_spool_free_index(sys_l2_ad_t* p_ad, void* user_data)
{
    sys_l2_ad_update_node_t  temp_node;
    sys_l2_ad_update_node_t* p_ad_node;
    uint32 ad_index = 0;
    int32 ret = 0;
    uint8  lchip = ((sys_l2_ad_param_t*)user_data)->lchip;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(p_ad);
    ad_index = p_ad->index;

    ret = sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, ad_index);

    if(ret)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "spool fress index failed,  line=%d\n",__LINE__);
        return -1;
    }

    if (!p_ad->ldp_en)
    {
        return 0;
    }


    temp_node.ad_index = p_ad->index;
    if(NULL == (p_ad_node = ctc_hash_lookup(pl2_usw_master[lchip]->ad_hash, &temp_node)))
    {
        return CTC_E_NONE;
    }
    /*overlay update ldp, remove node*/
    if (p_ad_node->ldp)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "remove l2 dsmac %d from ldp %d\n", p_ad->index, p_ad_node->ldp);
        sys_usw_remove_ldp_node(lchip, pl2_usw_master[lchip]->ldp_hash, p_ad_node->ldp, &p_ad_node->head);

    }

    if (p_ad_node->srv6_nhid)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "remove l2 dsmac %u from nhid %u\n", p_ad->index , p_ad_node->srv6_nhid);
        sys_usw_remove_ldp_node(lchip, pl2_usw_master[lchip]->nhid_hash, p_ad_node->srv6_nhid, &p_ad_node->nhid_list_head);
    }

    ctc_hash_remove(pl2_usw_master[lchip]->ad_hash, p_ad_node);
    mem_free(p_ad_node);
    return 0;
}

int32
_sys_usw_l2_flush_by_hw(uint8 lchip, ctc_l2_flush_fdb_t* p_flush, uint8 mac_limit_en, uint8 is_logic)
{
    drv_acc_in_t  acc_in;
    drv_acc_out_t acc_out;
    DsFibHost0MacHashKey_m fdb_key;
    hw_mac_addr_t   hw_mac = {0};
    uint32 max_index = 0;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();

    sal_memset(&acc_in, 0, sizeof(acc_in));
    sal_memset(&acc_out, 0, sizeof(acc_out));
    sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));

    if ((CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC == p_flush->flush_flag) && (!DRV_FROM_TMM(lchip)))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if (is_logic)
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_USE_LOGIC_PORT);
    }

    acc_in.type = DRV_FROM_TMM(lchip)?DRV_ACC_TYPE_FLUSH_FLEX : DRV_ACC_TYPE_FLUSH;
    sys_usw_ftm_query_table_entry_num(lchip, DsFibHost0MacHashKey_t, &max_index);
    acc_in.query_end_index = max_index+32;
    acc_in.query_cnt = SYS_L2_FLEX_OP_MAX_NUM;
    switch (p_flush->flush_type)
    {
    /* maybe need to add flush by port +vid */

    case CTC_L2_FDB_ENTRY_OP_BY_VID:

        acc_in.op_type = DRV_ACC_OP_BY_VLAN;
        SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, p_flush->fid);

        break;

    case CTC_L2_FDB_ENTRY_OP_BY_PORT:
        acc_in.op_type = DRV_ACC_OP_BY_PORT;

        if (p_flush->use_logic_port)
        {
            CTC_BIT_SET(acc_in.flag, DRV_ACC_USE_LOGIC_PORT);
            acc_in.gport = p_flush->gport;
        }
        else
        {
            acc_in.gport = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(p_flush->gport);
        }

        break;

    case CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN:
        acc_in.op_type =  (DRV_ACC_OP_BY_PORT | DRV_ACC_OP_BY_VLAN);
        SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, p_flush->fid);
        if (p_flush->use_logic_port)
        {
            CTC_BIT_SET(acc_in.flag, DRV_ACC_USE_LOGIC_PORT);
            acc_in.gport = p_flush->gport;
        }
        else
        {
            acc_in.gport = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(p_flush->gport);
        }
        break;

    case CTC_L2_FDB_ENTRY_OP_BY_MAC:
        acc_in.op_type = DRV_ACC_OP_BY_MAC;
        FDB_SET_HW_MAC(hw_mac, p_flush->mac);
        SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
        break;


    case CTC_L2_FDB_ENTRY_OP_ALL:
        acc_in.op_type = DRV_ACC_OP_BY_ALL;
        break;

    default:
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    /* add for mac limit*/
    if (0 != mac_limit_en)
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_UPDATE_MAC_LIMIT_CNT);
        if (pl2_usw_master[lchip]->static_fdb_limit)
        {
            CTC_BIT_SET(acc_in.flag, DRV_ACC_STATIC_MAC_LIMIT_CNT);
        }
    }

    acc_in.tbl_id = DsFibHost0MacHashKey_t;
    acc_in.module= DRV_ACC_HASH_MODULE_FDB;
    acc_in.data = &fdb_key;

    switch (p_flush->flush_flag)
    {
        case CTC_L2_FDB_ENTRY_STATIC:
            CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_STATIC);
            break;

        case CTC_L2_FDB_ENTRY_DYNAMIC:
        case CTC_L2_FDB_ENTRY_ALL:
            CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_DYNAMIC);
            break;
        case CTC_L2_FDB_ENTRY_PENDING:
            CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_PENDING);
            if(DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1))
            {
                /* learning cache enable */
                acc_in.type =  DRV_ACC_TYPE_FLUSH_CACHE;
                acc_out.is_end = 1;
            }
            break;
        case CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC:
            CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_LOCAL_DYNAMIC);
            break;
        default:
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
            return CTC_E_NOT_SUPPORT;

    }

    CTC_ERROR_RETURN(drv_acc_api(lchip, &acc_in, &acc_out));
    if(DRV_FROM_TMM(lchip))
    {
        while(!acc_out.is_end)
        {
            acc_in.index = acc_out.key_index;
            CTC_ERROR_RETURN(drv_acc_api(lchip, &acc_in, &acc_out));
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_l2_delete_hw_by_mac_fid(uint8 lchip, mac_addr_t mac, uint16 fid, uint8 mac_limit_en, uint8 is_logic, uint8 is_static)
{
    /*remove fail not return for syn with system*/
    hw_mac_addr_t    hw_mac;
    drv_acc_in_t   acc_in;
    drv_acc_out_t  acc_out;
    DsFibHost0MacHashKey_m fdb_key ;

    SYS_L2_INIT_CHECK();

    sal_memset(&acc_in, 0, sizeof(acc_in));
    sal_memset(&acc_out, 0, sizeof(acc_out));
    sal_memset(&fdb_key, 0, sizeof(fdb_key));

    acc_in.type = DRV_ACC_TYPE_DEL;
    acc_in.op_type = DRV_ACC_OP_BY_KEY;
    FDB_SET_HW_MAC(hw_mac, mac);
    SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, fid);
    SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);

    acc_in.tbl_id = DsFibHost0MacHashKey_t;
    acc_in.module= DRV_ACC_HASH_MODULE_FDB;
    acc_in.data = &fdb_key;

    /* add for mac limit*/
    if (0 != mac_limit_en && mac_limit_en != 0xFF)
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_UPDATE_MAC_LIMIT_CNT);
        if (pl2_usw_master[lchip]->static_fdb_limit)
        {
            CTC_BIT_SET(acc_in.flag, DRV_ACC_STATIC_MAC_LIMIT_CNT);
        }
    }
    if (is_logic)
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_USE_LOGIC_PORT);
    }

    if(is_static)
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_STATIC);

    }
    else
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_ENTRY_DYNAMIC);
    }
    if(mac_limit_en != 0xFF)
    {
        CTC_BIT_SET(acc_in.flag, DRC_ACC_PROFILE_MAC_LIMIT_EN);
    }
    else
    {
        CTC_BIT_SET(acc_in.flag, DRV_ACC_FORCE_STORE_SDB);
    }
    CTC_ERROR_RETURN(drv_acc_api(lchip, &acc_in, &acc_out));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_flush_fdb_cb(sys_l2_node_t* p_l2_node, sys_l2_flush_fdb_t* pf)
{
    uint8    is_dynamic = 0;
    uint8    mac_limit_en = 0;
    uint8    is_logic = 0;
    uint8    lchip = pf->lchip;
    uint16   gport = 0;
    uint8    learn_source = 0;
    uint32 cmd = 0;
    DsMac_m dsmac;
    /*system rsverved*/
    if(CTC_FLAG_ISSET(p_l2_node->flag, CTC_L2_FLAG_SYSTEM_RSV))
    {
        return 0;
    }

    is_logic = pf->use_logic_port;
    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_l2_node->adptr->index, cmd, &dsmac));
    learn_source = GetDsMac(V,learnSource_f, &dsmac);
    switch(pf->flush_type)
    {
        case CTC_L2_FDB_ENTRY_OP_BY_MAC:
            if(sal_memcmp(&p_l2_node->mac, &pf->mac,sizeof(mac_addr_t)))
            {
                return 0;
            }
            break;

        case CTC_L2_FDB_ENTRY_OP_BY_VID:
            if(pf->fid != p_l2_node->fid)
            {
                return 0;
            }
            break;
        case CTC_L2_FDB_ENTRY_OP_BY_PORT:
            if(learn_source)
            {
                gport = GetDsMac(V,logicSrcPort_f, &dsmac);
            }
            else
            {
                gport = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(GetDsMac(V, globalSrcPort_f, &dsmac));
            }
            if((learn_source != is_logic) || pf->gport != gport)
            {
                return 0;
            }
            break;
        case CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN:
            if(learn_source)
            {
                gport = GetDsMac(V,logicSrcPort_f, &dsmac);
            }
            else
            {
                gport = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(GetDsMac(V, globalSrcPort_f, &dsmac));
            }
            if((learn_source != is_logic) || pf->gport != gport ||  pf->fid != p_l2_node->fid )
            {
                return 0;
            }
            break;

        case CTC_L2_FDB_ENTRY_OP_ALL:
            break;
        default:
            return 0;

    }
    is_dynamic = !CTC_FLAG_ISSET(p_l2_node->flag, CTC_L2_FLAG_IS_STATIC);
    mac_limit_en = (is_dynamic || pl2_usw_master[lchip]->static_fdb_limit)?1:0;

    if((pf->flush_flag == CTC_L2_FDB_ENTRY_STATIC && is_dynamic) ||
                        ((pf->flush_flag == CTC_L2_FDB_ENTRY_DYNAMIC || pf->flush_flag ==CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC) && !is_dynamic) || ((pf->flush_flag ==
                        CTC_L2_FDB_ENTRY_LOCAL_DYNAMIC)&& CTC_FLAG_ISSET(p_l2_node->flag, CTC_L2_FLAG_REMOTE_DYNAMIC)))
    {
        return 0 ;
    }

    /*No need to update port mac limit for logic port or ecmp*/
    is_logic = is_logic || p_l2_node->ecmp_valid;
    sys_usw_l2_delete_hw_by_mac_fid(lchip, p_l2_node->mac, p_l2_node->fid, mac_limit_en, is_logic, CTC_FLAG_ISSET(p_l2_node->flag, CTC_L2_FLAG_IS_STATIC));

    if (p_l2_node->bind_nh)
    {
        _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 0, 0, 0);
    }
    if (p_l2_node->rsv_ad)
    {
        mem_free(p_l2_node->adptr);
    }
    else
    {
        _sys_usw_l2_dsmac_spool_remove(lchip, p_l2_node->adptr, NULL);
    }

    mem_free(p_l2_node);
    return 1;
}

STATIC int32
_sys_usw_l2_unbinding_logic_ecmp(uint8 lchip, ctc_l2_flush_fdb_t* pf, uint8 unbinding, void* p_mac)
{
    sys_l2_fid_node_t* p_fid_node = NULL;
    sys_l2_vport_2_nhid_t* p_vport_node = NULL;
    uint32                 cmd     = 0;
    sys_nh_info_dsnh_t p_nhinfo;
    DsMac_m              ds_mac;

    sal_memset(&p_nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    sal_memset(&ds_mac, 0, sizeof(ds_mac));

    if (!pl2_usw_master[lchip]->cfg_hw_learn || (0 == pf->use_logic_port) || (CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN != pf->flush_type))
    {
        return CTC_E_NONE;
    }

    p_vport_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, pf->gport);
    p_fid_node = ctc_vector_get(pl2_usw_master[lchip]->fid_vec, pf->fid);
    if ((NULL == p_vport_node)||(NULL == p_fid_node))
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_vport_node->nhid, &p_nhinfo, 0));
    if (!p_nhinfo.ecmp_valid)
    {
        return CTC_E_NONE;
    }

    if (unbinding)/* set to vlan default entry when flushing*/
    {
        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_vport_node->ad_idx, cmd, &ds_mac));
        sal_memcpy(p_mac, &ds_mac, sizeof(DsMac_m));

        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, DEFAULT_ENTRY_INDEX(pf->fid), cmd, &ds_mac));
        SetDsMac(V, logicSrcPort_f, &ds_mac, pf->gport);
        SetDsMac(V, isStatic_f, &ds_mac, 0);
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_vport_node->ad_idx, cmd, &ds_mac));
    }
    else /* recover to nexthop after flush*/
    {
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_vport_node->ad_idx, cmd, p_mac));
    }

    return CTC_E_NONE;
}
int32
_sys_usw_l2_flush_fdb_by_fid_cb(void* array_data, void* user_data)
{
    sys_l2_fid_node_t *p_fid = (sys_l2_fid_node_t *)array_data;
    sys_l2_flush_fdb_t* pf = (sys_l2_flush_fdb_t*)user_data;
    ctc_l2_flush_fdb_t flush;
    if(!CTC_FLAG_ISSET(p_fid->flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT))
    {
        return CTC_E_NONE;
    }

    sal_memset(&flush, 0, sizeof(flush));
    flush.flush_flag = pf->flush_flag;
    flush.flush_type = CTC_L2_FDB_ENTRY_OP_BY_VID;
    flush.fid = p_fid->fid;

    return _sys_usw_l2_flush_by_hw(pf->lchip, &flush, 1, 1);
}
int32
sys_usw_l2_flush_fdb(uint8 lchip, ctc_l2_flush_fdb_t* pf)
{
    int32                      ret = CTC_E_NONE;
    sys_l2_flush_fdb_t   sys_flush;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(pf);
    CTC_ERROR_RETURN(_sys_usw_l2_query_flush_check(lchip, pf, 1));


    if(CTC_L2_FDB_ENTRY_OP_BY_MAC_VLAN == pf->flush_type)
    {
        ctc_l2_addr_t   l2_addr;

        sal_memset(&l2_addr, 0, sizeof(ctc_l2_addr_t));
        l2_addr.fid = pf->fid;
        sal_memcpy(l2_addr.mac, pf->mac, sizeof(mac_addr_t));
        ret =  sys_usw_l2_remove_fdb(lchip, &l2_addr);
        goto end;
    }
    else if ((CTC_L2_FDB_ENTRY_PENDING == pf->flush_flag) && (!DRV_FROM_TMM(lchip)))
    {
        ctc_l2_fdb_query_t query;
        ctc_l2_fdb_query_rst_t query_rst;
        uint32 loop = 0;
        uint16 fid = 0;
        uint8  is_logic = 0;
        mac_addr_t mac = {0};

        sal_memset(&query, 0, sizeof(query));
        sal_memset(&query_rst, 0, sizeof(query_rst));
        query.query_flag = CTC_L2_FDB_ENTRY_PENDING;
        query.query_type = CTC_L2_FDB_ENTRY_OP_ALL;

        MALLOC_ZERO(MEM_FDB_MODULE, query_rst.buffer, DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t));
        if(NULL == query_rst.buffer)
        {
            ret =  CTC_E_NO_MEMORY;
            goto end;
        }

        query_rst.buffer_len = DUMP_MAX_ENTRY*sizeof(ctc_l2_addr_t);

        L2_LOCK;
        do
        {
            /* 1. dump all pending entry*/
            query.count = 0;
            query_rst.start_index = query_rst.next_query_index ;
            if((ret = _sys_usw_l2_get_entry_by_hw(lchip, &query, &query_rst, 0, 0, NULL)) < 0)
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "flush pending fdb error\n");
                mem_free(query_rst.buffer);
                L2_UNLOCK;
                goto end;
            }

            /* 2. delete entry one by one*/
            for(loop=0; loop<query.count;loop++)
            {
                fid = (query_rst.buffer+loop)->fid;
                is_logic = SYS_L2_IS_LOGIC_PORT(fid);
                sal_memcpy(&mac, &((query_rst.buffer+loop)->mac), sizeof(mac_addr_t));

                sys_usw_l2_delete_hw_by_mac_fid(lchip, mac, fid, 1,  is_logic, 0);
            }
        }while(!query_rst.is_end);

        mem_free(query_rst.buffer);
        L2_UNLOCK;
        goto end;

    }
    else if ((CTC_L2_FDB_ENTRY_PENDING == pf->flush_flag) && DRV_FROM_TMM(lchip))
    {
        L2_LOCK;
        _sys_usw_l2_flush_by_hw(lchip, pf, 1, pf->use_logic_port);
        L2_UNLOCK;
        goto end;
    }

    sys_flush.fid = pf->fid;
    sys_flush.flush_flag = pf->flush_flag;
    sys_flush.flush_type = pf->flush_type;
    sys_flush.lchip = lchip;
    sal_memcpy(&sys_flush.mac, pf->mac, sizeof(mac_addr_t));
    sys_flush.gport = pf->gport;
    sys_flush.use_logic_port = pf->use_logic_port;
    L2_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
    ctc_hash_traverse_remove(pl2_usw_master[lchip]->fdb_hash, (hash_traversal_fn)_sys_usw_l2_flush_fdb_cb, &sys_flush);
    if(pf->flush_flag != CTC_L2_FDB_ENTRY_STATIC)
    {
        DsMac_m ds_mac;
        uint32 cmd;
        uint32 field_value;
        if(DRV_IS_DUET2(lchip))
        {
            _sys_usw_l2_unbinding_logic_ecmp(lchip, pf, 1, &ds_mac);
            ret = _sys_usw_l2_flush_by_hw(lchip, pf, 1, pf->use_logic_port);
            _sys_usw_l2_unbinding_logic_ecmp(lchip, pf, 0, &ds_mac);
        }
        else if(DRV_IS_TSINGMA(lchip))
        {
            if((pf->flush_type == CTC_L2_FDB_ENTRY_OP_ALL) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
            {
                /*for ecmp fdb, flush all fdb will delete fdb but not update mac limit count*/
                field_value = 0;
                cmd = DRV_IOW(FibAccelerationCtl_t, FibAccelerationCtl_logicPortIgnoreMode_f);
                DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value);
            }
            ret = _sys_usw_l2_flush_by_hw(lchip, pf, 1, pf->use_logic_port);

            if((pf->flush_type == CTC_L2_FDB_ENTRY_OP_ALL) && (SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A))
            {
                field_value = 1;
                cmd = DRV_IOW(FibAccelerationCtl_t, FibAccelerationCtl_logicPortIgnoreMode_f);
                DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value);
            }
            if(pf->flush_type == CTC_L2_FDB_ENTRY_OP_ALL)
            {
                ctc_l2_fdb_query_t query_cnt;
                sal_memset(&query_cnt, 0, sizeof(query_cnt));
                query_cnt.query_type = CTC_L2_FDB_ENTRY_OP_ALL;
                query_cnt.query_flag = CTC_L2_FDB_ENTRY_DYNAMIC;
                if((CTC_E_NONE == _sys_usw_l2_get_count_by_all(lchip, &query_cnt)) && query_cnt.count)
                {
                    ctc_vector_traverse(pl2_usw_master[lchip]->fid_vec, _sys_usw_l2_flush_fdb_by_fid_cb, &sys_flush);
                }
            }
        }
        else
        {
            ret = _sys_usw_l2_flush_by_hw(lchip, pf, 1, pf->use_logic_port);
        }
    }

    L2_UNLOCK;
end:
    return ret;
}


#define _FDB_HW_
STATIC int32
_sys_usw_l2_build_tcam_key(uint8 lchip, mac_addr_t mac, uint32 ad_index, void* mackey)
{
    hw_mac_addr_t hw_mac;

    CTC_PTR_VALID_CHECK(mackey);
    sal_memset(mackey, 0, sizeof(DsFibMacBlackHoleHashKey_m));

    FDB_SET_HW_MAC(hw_mac, mac);
    SetDsFibMacBlackHoleHashKey(A, mappedMac_f, mackey, hw_mac);
    SetDsFibMacBlackHoleHashKey(V, valid_f, mackey, 1);
    SetDsFibMacBlackHoleHashKey(V, dsAdIndex_f, mackey, ad_index);

    return CTC_E_NONE;

}
STATIC int32
_sys_usw_l2_write_hw(uint8 lchip, sys_l2_info_t* psys)//vlan_default_entry
{
    uint32   cmd  = 0;
    uint16   fid  = 0;
    DsMac_m ds_mac;
    hw_mac_addr_t   hw_mac = {0};
    uint32     flag     = 0;
    uint32     gport = 0;
    uint8       xgpon_en = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sys_usw_global_get_xgpon_en(lchip, &xgpon_en);

    if ((!psys->rsv_ad_index || xgpon_en) && !psys->hw_reset)
    {
        /* write Ad */
        CTC_ERROR_RETURN(_sys_usw_l2_encode_dsmac(lchip, &ds_mac, psys));
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, psys->ad_index, cmd, &ds_mac));
    }

    switch(psys->addr_type)
    {
        case SYS_L2_ADDR_TYPE_UC:
            fid = psys->addr.l2_addr.fid;
            flag = psys->addr.l2_addr.flag;
            gport = psys->addr.l2_addr.gport;
            FDB_SET_HW_MAC(hw_mac, psys->addr.l2_addr.mac);
            break;
        case SYS_L2_ADDR_TYPE_MC:
            fid = psys->addr.l2mc_addr.fid;
            flag = psys->addr.l2mc_addr.flag;
            FDB_SET_HW_MAC(hw_mac, psys->addr.l2mc_addr.mac);
            break;
        default:
            break;
    }

    if (fid == DONTCARE_FID) /* tcam */
    {
        DsFibMacBlackHoleHashKey_m tcam_key;
        _sys_usw_l2_build_tcam_key(lchip, psys->addr.l2_addr.mac, psys->ad_index, &tcam_key);
        cmd = DRV_IOW(DsFibMacBlackHoleHashKey_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, psys->key_index, cmd, &tcam_key));
    }
    else if (!(psys->addr_type == SYS_L2_ADDR_TYPE_DEFAULT)) /* uc or mc */
    {
        drv_acc_in_t  in;
        drv_acc_out_t out;
        uint8 is_dynamic;
        DsFibHost0MacHashKey_m fdb_key;

        sal_memset(&in, 0, sizeof(in));
        sal_memset(&out, 0, sizeof(out));
        sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));
        /* write Key */
        if (MCHIP_FDB(lchip)->key_encode)
        {
            MCHIP_FDB(lchip)->key_encode(lchip, &fdb_key, hw_mac, fid, psys->ad_index);
        }
        else
        {
            SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, fid);
            SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
            SetDsFibHost0MacHashKey(V, dsAdIndex_f, &fdb_key, psys->ad_index);
            SetDsFibHost0MacHashKey(V, valid_f, &fdb_key, 1);
            SetDsFibHost0MacHashKey(V, hashType_f, &fdb_key, DRV_ENUM(DRV_FIBHOST0PRIMARYHASHTYPE_MAC));
        }
        in.type = DRV_ACC_TYPE_ADD;
        in.op_type = DRV_ACC_OP_BY_KEY;
        in.tbl_id = DsFibHost0MacHashKey_t;
        in.module= DRV_ACC_HASH_MODULE_FDB;
        in.data = &fdb_key;
        /*for white list entry do not aging */
        if (CTC_FLAG_ISSET(flag,CTC_L2_FLAG_WHITE_LIST_ENTRY)|| CTC_FLAG_ISSET(flag,CTC_L2_FLAG_AGING_DISABLE))
        {
            in.timer_index = 0;
        }
        else if (!CTC_FLAG_ISSET(flag,CTC_L2_FLAG_IS_STATIC)) /* pending entry already set aging status.*/
        {
            in.timer_index = SYS_AGING_TIMER_INDEX_MAC;
            CTC_BIT_SET(in.flag, DRV_ACC_AGING_EN);
        }

        is_dynamic = (!CTC_FLAG_ISSET(flag,CTC_L2_FLAG_IS_STATIC) && (psys->addr_type != SYS_L2_ADDR_TYPE_MC));

        if (is_dynamic || (pl2_usw_master[lchip]->static_fdb_limit && (psys->addr_type != SYS_L2_ADDR_TYPE_MC)))
        {
            CTC_BIT_SET(in.flag, DRV_ACC_UPDATE_MAC_LIMIT_CNT);

            if(is_dynamic)
            {
                CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
            }

            /*No need to update port mac limit for logic port or ecmp*/
            if (psys->is_logic_port || psys->ecmp_valid)
            {
                CTC_BIT_SET(in.flag, DRV_ACC_USE_LOGIC_PORT);
            }

            in.gport = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(gport);

            if (pl2_usw_master[lchip]->static_fdb_limit)
            {
                CTC_BIT_SET(in.flag, DRV_ACC_STATIC_MAC_LIMIT_CNT);
            }
        }
        if(psys->addr_type != SYS_L2_ADDR_TYPE_MC)
        {
            CTC_BIT_SET(in.flag, DRC_ACC_PROFILE_MAC_LIMIT_EN);
        }
        else
        {
            CTC_BIT_SET(in.flag, DRV_ACC_FORCE_STORE_SDB);
        }

        CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
        if (out.is_conflict)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Hash Conflict\n");
            return CTC_E_HASH_CONFLICT;
        }

        if (out.is_full)
        {
            uint8 learn_cache_en = DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1) ? 1 : 0;
            if (learn_cache_en)
            {
                in.type = DRV_ACC_TYPE_FLUSH_CACHE;
                CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
            }
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [FDB] Security violation \n");
            return CTC_E_NO_RESOURCE;

        }
        psys->key_index = out.key_index;
    }

    return CTC_E_NONE;
}

int32
sys_usw_l2_dump_l2master(uint8 lchip)
{
    SYS_L2_INIT_CHECK();
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "ad_index_drop              0x%x \n" \
                     "dft_entry_base             0x%x \n" \
                     "max_fid_value              0x%x \n" \
                     "hw_learn_en                0x%x \n" ,
                     pl2_usw_master[lchip]->ad_index_drop,       \
                     pl2_usw_master[lchip]->dft_entry_base,      \
                     pl2_usw_master[lchip]->cfg_max_fid,         \
                     pl2_usw_master[lchip]->cfg_hw_learn);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "hw_aging_en                0x%x \n", pl2_usw_master[lchip]->cfg_hw_learn);
    if (!pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "base_vport                 0x%x \n" , sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT));
    }
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,
             "base_gport                 0x%x \n" \
             "base_trunk                 0x%x \n" \
             "logic_port_num             0x%x \n",
             sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT),   \
             sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK),   \
             pl2_usw_master[lchip]->cfg_vport_num);

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_add_tcam(uint8 lchip, ctc_l2_addr_t* l2_addr, uint8 with_nh, uint32 nhid)
{
    int32          ret    = 0;
    uint32         key_index = 0;
    uint32         ad_index = 0;
    uint8         is_exist = 0;
    sys_l2_info_t  sys;
    uint32        cmd = DRV_IOR(DsFibMacBlackHoleHashKey_t, DsFibMacBlackHoleHashKey_dsAdIndex_f);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&sys, 0, sizeof(sys));

    L2_LOCK;
    CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_TCAM, l2_addr, &sys, with_nh, nhid), ret, error_0);

    /* 1.  lookup tcam_hash */
    is_exist = _sys_usw_l2_black_hole_lookup(lchip, l2_addr->mac, &key_index, NULL);
    if (!is_exist)
    {
        for(key_index=0; key_index<SYS_L2_MAX_BLACK_HOLE_ENTRY; key_index++)
        {
            if(!CTC_BMP_ISSET(pl2_usw_master[lchip]->mac_fdb_bmp, key_index))
            {
                CTC_BMP_SET(pl2_usw_master[lchip]->mac_fdb_bmp, key_index);
                break;
            }
        }

        if(key_index == SYS_L2_MAX_BLACK_HOLE_ENTRY)
        {
            ret =  CTC_E_NO_RESOURCE;
            goto error_0;
        }

        CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, 1, 1, &ad_index), ret, error_1);

        sys.key_index  = key_index;
        sys.ad_index   = ad_index;
        CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &sys), ret, error_2);

    }
    else
    {
        DsMac_m ds_mac;
        CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, key_index, cmd, &sys.ad_index), ret, error_0);
        sys.key_index = key_index;
        CTC_ERROR_GOTO(_sys_usw_l2_encode_dsmac(lchip, &ds_mac, &sys), ret, error_0);
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, sys.ad_index, cmd, &ds_mac), ret, error_0);

    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "key index:%d, ad_index:%d\n",sys.key_index,sys.ad_index);

    L2_UNLOCK;
    return CTC_E_NONE;

error_2:
    sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, ad_index);
error_1:
    CTC_BMP_UNSET(pl2_usw_master[lchip]->mac_fdb_bmp, key_index);
error_0:
    L2_UNLOCK;
    return ret;
}

STATIC int32
_sys_usw_l2_remove_tcam(uint8 lchip, ctc_l2_addr_t* l2_addr)
{
    sys_l2_info_t  sys;
    uint32         cmd   = 0;
    DsFibMacBlackHoleHashKey_m empty;
    int32 ret = 0;
    uint8 is_exist = 0;
    uint32 ad_index = 0;

    L2_LOCK;

    sal_memcpy(&sys.addr.l2_addr, l2_addr, sizeof(ctc_l2_addr_t));

    is_exist = _sys_usw_l2_black_hole_lookup(lchip, l2_addr->mac, &sys.key_index, &ad_index);
    if (is_exist)
    {
         /*write key*/
        sal_memset(&empty, 0, sizeof(empty));
        cmd = DRV_IOW(DsFibMacBlackHoleHashKey_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, sys.key_index, cmd, &empty), ret, error_proc);

         /*free ds mac*/
        sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, ad_index);

         /*free bitmap*/
        CTC_BMP_UNSET(pl2_usw_master[lchip]->mac_fdb_bmp, sys.key_index);
    }
    else
    {
        ret = CTC_E_NOT_EXIST;
    }

error_proc:

    L2_UNLOCK;

    return ret;
}

STATIC int32
_sys_usw_l2_fdb_check(uint8 lchip, ctc_l2_addr_t* l2_addr, uint8 with_nh, uint32 nhid)
{
    uint32 temp_flag = 0;
    uint16 fid_flag = 0;
    uint8 is_logic_port =0;

    SYS_USW_CID_CHECK(lchip,l2_addr->cid);
    if (l2_addr->service_id >= MCHIP_CAP(SYS_CAP_SERVICE_ID_NUM))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_IS_STATIC)&& CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_REMOTE_DYNAMIC))
    {
        return CTC_E_INVALID_PARAM;
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
     /* 1. check flag supported*/
    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_WHITE_LIST_ENTRY) && ((!with_nh) || CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_IS_STATIC)))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (!with_nh && CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT)&& !CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_DISCARD))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_UCAST_DISCARD))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if (!DRV_FROM_AT(lchip) && NULL != l2_addr->xdata)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
    }

    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_RMAC_MATCH) && !CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_IS_STATIC))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Router Mac Match only support static FDB \n");
        return CTC_E_NOT_SUPPORT;
    }

    if (l2_addr->cid && l2_addr->service_id)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " FDB can not support cid and service_id at the same time\n");
        return CTC_E_NOT_SUPPORT;
    }
    fid_flag = _sys_usw_l2_get_fid_flag(lchip, l2_addr->fid);
    is_logic_port = CTC_FLAG_ISSET(fid_flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT);

     /* 2. check parameter*/
     if (!with_nh && !CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_DISCARD) && !is_logic_port)
    {
        SYS_GLOBAL_PORT_CHECK(l2_addr->gport);
    }
    else if (is_logic_port)
    {
        SYS_LOGIC_PORT_CHECK(l2_addr->gport);
    }

    if (!CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_IS_STATIC))
    {
        temp_flag = l2_addr->flag;
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_AGING_DISABLE);
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_REMOTE_DYNAMIC);
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_BIND_PORT);
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_WHITE_LIST_ENTRY);
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT);
        if(!pl2_usw_master[lchip]->cfg_hw_learn)
        {
            CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_SRC_DISCARD);
            CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_DISCARD);
        }
        CTC_UNSET_FLAG(temp_flag, CTC_L2_FLAG_PON_EN);
        if (temp_flag) /* dynamic entry has other flag */
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    if (with_nh)
    {
        if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT))
        {
            SYS_GLOBAL_PORT_CHECK(l2_addr->gport);
        }
    }

    if(with_nh && (1 == nhid || 2 == nhid) && CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT))
    {
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_map_xdata_info(sys_l2_info_t*       psys, ctc_xdata_field_t* temp_fields)
{
    CTC_PTR_VALID_CHECK(temp_fields);

    if(SYS_L2_ADDR_TYPE_UC == psys->addr_type)
    {
        if(SYS_FDB_XD_OFF_TRUNK0((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_AUX);
        }
        else if(SYS_FDB_XD_OFF_TRUNK1((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_POL);
        }
        else if(SYS_FDB_XD_OFF_TRUNK2((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_STA);
        }
        else if(SYS_FDB_XD_OFF_TRUNK3((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_FWD);
        }
        else
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else if(SYS_L2_ADDR_TYPE_DEFAULT == psys->addr_type)
    {
        if(SYS_DEFAULT_XD_OFF_TRUNK0((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_AUX);
        }
        else if(SYS_DEFAULT_XD_OFF_TRUNK1((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_CID);
        }
        else if(SYS_DEFAULT_XD_OFF_TRUNK2((temp_fields->offset), temp_fields->width - 1))
        {
            CTC_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_XDA);
        }
        else
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_xdata_check(uint8 lchip, sys_l2_info_t* psys)
{
    ctc_xdata_t* xdata = NULL;
    ctc_xdata_field_t*  temp_fields = NULL;
    uint8 num = 0;
    uint8 station_move_mode =0;
    
    CTC_ERROR_RETURN(DRV_FROM_AT(lchip)? CTC_E_NONE : CTC_E_NOT_SUPPORT);
    
    sys_usw_global_get_station_move_mode(lchip, &station_move_mode);
    if (station_move_mode)
    {
        return  CTC_E_INVALID_PARAM;
    }
    xdata = psys->xdata.info;

    if(CTC_XDATA_PROF_TYPE_DSMACDA != xdata->type || ((SYS_L2_ADDR_TYPE_UC == psys->addr_type && SYS_FDB_XDATA_PROFILE_ID != xdata->prof_id )||
              (SYS_L2_ADDR_TYPE_DEFAULT == psys->addr_type && SYS_DFT_XDATA_PROFILE_ID != xdata->prof_id)))
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(MCHIP_XDATA(lchip)->prof_get_info(lchip, xdata, 1));

    for (num = 0; num < xdata->num; num++)
    {
        temp_fields = &(xdata->fields[num]);
        CTC_ERROR_RETURN(_sys_usw_l2_map_xdata_info(psys, temp_fields));
        SYS_USW_SET_XDATA(temp_fields->width, temp_fields->offset, temp_fields->data, psys->xdata.value);
    }

    switch (psys->addr_type)
    {
        case SYS_L2_ADDR_TYPE_UC:
            if((CTC_IS_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_POL)  && ((0 != psys->addr.l2_addr.policer_id) || CTC_FLAG_ISSET(psys->addr.l2_addr.flag, CTC_L2_FLAG_COPY_TO_CPU) || \
                (0 != psys->addr.l2_addr.service_id) || (0 != psys->addr.l2_addr.cid))) || \
               (CTC_IS_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_STA) && (psys->merge_dsfwd || (!psys->merge_dsfwd && psys->ecmp_valid))))
            {
                return CTC_E_PARAM_CONFLICT;
            }
            else if (CTC_IS_BIT_SET(psys->xdata.field, SYS_FDB_XDATA_FIELD_FWD))
            {
                return CTC_E_NOT_SUPPORT;
            }
            break;
       case SYS_L2_ADDR_TYPE_DEFAULT:
            if(CTC_IS_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_CID) && (0 != psys->addr.l2df_addr.cid))
            {
                return CTC_E_PARAM_CONFLICT;
            }
            else if(CTC_IS_BIT_SET(psys->xdata.field, SYS_DFT_XDATA_FIELD_XDA))
            {
                return CTC_E_NOT_SUPPORT;
            }
            break;
       default:
            return  CTC_E_INVALID_PARAM;
            break;
    }

    return CTC_E_NONE;
}

/**
   @brief add fdb entry
   @param force_overwrite: allow dynamic entry overwrite static entry, only can used by sys_usw_l2_replace_match_fdb
 */
int32
sys_usw_l2_add_fdb(uint8 lchip, ctc_l2_addr_t* l2_addr, uint8 with_nh, uint32 nhid, uint8 force_overwrite)
{
    sys_l2_info_t       new_sys;
    int32               ret         = 0;
    mac_lookup_result_t result = {0};
    sys_l2_info_t       old_sys;
    sys_l2_node_t*      p_l2_node_old = NULL;
    sys_l2_node_t*      p_l2_node  = NULL;
    uint8               is_overwrite = 0;
    sys_l2_ad_t         l2_ad;
    sys_l2_ad_t*        p_old_ad = NULL;
    uint8  bind_flag = 0;
    uint8  need_has_sw = 0;
    uint8   old_rsv_ad = 0;
    uint8   old_is_static = 0;
    sys_l2_node_t l2_node_old;
    DsMac_m dsmac;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);

    sal_memset(&new_sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&old_sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&l2_node_old, 0, sizeof(sys_l2_node_t));

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s ,fid :%d ,flag:0x%x, gport:0x%x\n",
                      sys_output_mac(l2_addr->mac), l2_addr->fid, l2_addr->flag, l2_addr->gport);

    if (l2_addr->fid ==  DONTCARE_FID) /* is_tcam is set when system mac. and system mac can update */
    {
        return _sys_usw_l2_add_tcam(lchip, l2_addr, with_nh, nhid);
    }

    L2_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_l2_fdb_check(lchip, l2_addr,with_nh, nhid), pl2_usw_master[lchip]->l2_mutex);

    if (SYS_L2_IS_LOGIC_PORT(l2_addr->fid))
    {
        SYS_LOGIC_PORT_CHECK_WITH_UNLOCK(l2_addr->gport, pl2_usw_master[lchip]->l2_mutex);
    }

     /* 4. map ctc to sys  _sys_usw_l2_build_sys_info*/

    CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_UC, l2_addr, &new_sys, with_nh, nhid), ret, error_init);

     /* 5. lookup hw, check result*/
    CTC_ERROR_GOTO(_sys_usw_l2_acc_lookup_mac_fid
                    (lchip, l2_addr->mac, l2_addr->fid, &result), ret, error_init);
    new_sys.key_index = result.key_index;

    if (result.conflict)
    {
        if(pl2_usw_master[lchip]->search_depth)
        {
            CTC_ERROR_GOTO(_sys_usw_l2_fdb_hash_reorder_algorithm(lchip, l2_addr), ret, error_init);
        }
        else
        {
            ret = CTC_E_HASH_CONFLICT;
            goto error_init;
        }
    }

     /* 6. if hit means entry already exist, pending entry has clear hit flag in driver*/
    is_overwrite = result.hit;

    if (result.pending)
    {
        new_sys.pending = 1;
    }

    p_l2_node_old = _sys_usw_l2_fdb_hash_lkup(lchip, &l2_addr->mac, l2_addr->fid);

    if (is_overwrite)
    {
        CTC_ERROR_GOTO(_sys_usw_l2_build_sys_ad_info_by_index(lchip, result.ad_index, &old_sys), ret, error_init);
        /* l2 mc shall not ovewrite */
        if (SYS_L2_ADDR_TYPE_MC == old_sys.addr_type && !p_l2_node_old)
        {
            if(!(new_sys.is_logic_port && pl2_usw_master[lchip]->vp_alloc_ad_en))
            {
                ret = CTC_E_EXIST;
                goto error_init;
            }
        }

        /*note: static fdb with mcast nexthop*/
        old_is_static = (((SYS_L2_ADDR_TYPE_UC == old_sys.addr_type) && CTC_FLAG_ISSET(old_sys.addr.l2_addr.flag, CTC_L2_FLAG_IS_STATIC)) || 
                         ((SYS_L2_ADDR_TYPE_MC == old_sys.addr_type) && CTC_FLAG_ISSET(old_sys.addr.l2mc_addr.flag, CTC_L2_FLAG_IS_STATIC))) ? 1 : 0;

        /* dynamic cannot rewrite static */
        if (!force_overwrite && !CTC_FLAG_ISSET(new_sys.addr.l2_addr.flag, CTC_L2_FLAG_IS_STATIC) && old_is_static)
        {
            ret = CTC_E_EXIST;
            goto error_init;
        }

    }

    if(p_l2_node_old)
    {
        p_old_ad = p_l2_node_old->adptr;
        old_rsv_ad = p_l2_node_old->rsv_ad;
    }
    /*build dsmac index*/
    CTC_ERROR_GOTO(_sys_usw_l2_get_reserved_index(lchip, &new_sys), ret, error_init);

    need_has_sw = ((!new_sys.rsv_ad_index)&&(!(new_sys.is_logic_port&&CTC_FLAG_ISSET(new_sys.addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC)))) || ((new_sys.use_destmap_profile || new_sys.ecmp_valid) && DRV_IS_DUET2(lchip));
    if (need_has_sw)
    {
        sys_l2_ad_t*         p_ad = NULL;
        sal_memset(&l2_ad, 0, sizeof(l2_ad));

        if(p_l2_node_old)
        {
            sal_memcpy(&l2_node_old, p_l2_node_old, sizeof(sys_l2_node_t));
            p_l2_node_old->flag = l2_addr->flag;
            p_l2_node_old->ecmp_valid = new_sys.ecmp_valid;
            p_l2_node_old->use_destmap_profile = new_sys.use_destmap_profile;
            p_l2_node_old->aps_valid = new_sys.aps_valid;
            p_l2_node_old->rsv_ad    = new_sys.rsv_ad_index;
            p_l2_node_old->key_index = new_sys.key_index;
            p_l2_node = p_l2_node_old;

            /*update to unbind nexthop*/
            if (p_l2_node->bind_nh)
            {
                _sys_usw_l2_bind_nexthop(lchip, p_l2_node_old, 0, 0, 0);
            }

        }
        else
        {
        #ifdef WARMBOOT
            if(CTC_WB_ENABLE(lchip) && pl2_usw_master[lchip]->fdb_hash->count >= SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_STATIC_FDB))
            {
                ret = CTC_E_NO_RESOURCE;
                goto error_init;
            }
        #endif
            MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node, sizeof(sys_l2_node_t));
            if(NULL == p_l2_node)
            {
                ret = CTC_E_NO_MEMORY;
                goto error_init;
            }

            sal_memcpy(&p_l2_node->mac, &l2_addr->mac, sizeof(mac_addr_t));
            p_l2_node->fid  = l2_addr->fid;
            p_l2_node->flag = l2_addr->flag;
            p_l2_node->ecmp_valid = new_sys.ecmp_valid;
            p_l2_node->use_destmap_profile = new_sys.use_destmap_profile;
            p_l2_node->aps_valid = new_sys.aps_valid;
            p_l2_node->rsv_ad    = new_sys.rsv_ad_index;
        }

        p_l2_node->nh_id = new_sys.nhid;


        if (new_sys.bind_nh)
        {
            /*do not using dsfwd, do nexthop and l2 bind*/
            ret = _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 1, 0, 0);
            if (CTC_E_IN_USE == ret)
            {
                /*nh have already bind, do unbind, using dsfwd*/
                CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, nhid, &new_sys.fwd_ptr, 0, CTC_FEATURE_L2), ret, error_0);
                new_sys.merge_dsfwd = 0;
                new_sys.bind_nh = 0;
            }
            else if (ret < 0)
            {
                /*Bind fail, using dsfwd*/
                CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, nhid, &new_sys.fwd_ptr, 0, CTC_FEATURE_L2), ret, error_0);
                new_sys.merge_dsfwd = 0;
                new_sys.bind_nh = 0;
            }
            else
            {
                /*indicate bind success*/
                bind_flag = 1;
            }
        }
        if(new_sys.xdata_en)
        {
            CTC_ERROR_GOTO(_sys_usw_l2_xdata_check(lchip, &new_sys), ret, error_0);
        }
        CTC_ERROR_GOTO(_sys_usw_l2_encode_dsmac(lchip, &dsmac, &new_sys), ret, error_0);
        if (p_l2_node->rsv_ad)
        {
            MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node->adptr, sizeof(sys_l2_ad_t));
            if(NULL == p_l2_node->adptr)
            {
                ret = CTC_E_NO_MEMORY;
                goto error_0;
            }
            p_l2_node->adptr->index = new_sys.ad_index;
        }
        else if (!(new_sys.is_logic_port && CTC_FLAG_ISSET(new_sys.addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC)))
        {
            if (new_sys.with_nh)
            {
                sys_nh_info_dsnh_t nhinfo;
                sal_memset(&nhinfo, 0, sizeof(nhinfo));
                CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, new_sys.nhid, &nhinfo, 0), ret, error_0);
                if (nhinfo.nh_entry_type == SYS_NH_TYPE_OVERLAY)
                {
                    l2_ad.param.ldp = new_sys.addr.l2_addr.gport;
                }
                if (nhinfo.nh_entry_type == SYS_NH_TYPE_SRV6)
                {
                    l2_ad.param.srv6_nhid = new_sys.nhid;
                    l2_ad.param.ldp = SYS_COM_LDP_SRH_ID(new_sys.tunnel_id);
                }
            }
            l2_ad.param.ldp = new_sys.use_lp? new_sys.addr.l2_addr.gport : l2_ad.param.ldp;
            l2_ad.param.ds_mac = &dsmac;
            CTC_ERROR_GOTO(_sys_usw_l2_dsmac_spool_add(lchip, &l2_ad, &p_ad), ret, error_0);
            l2_ad.index = p_ad->index;
            p_l2_node->adptr = p_ad;
            new_sys.ad_index = p_ad->index;
        }
        else
        {
            l2_ad.index = new_sys.ad_index;
        }

        if (!p_l2_node_old)
        {
            CTC_ERROR_GOTO(_sys_usw_l2_fdb_hash_add(lchip, p_l2_node), ret, error_1);
        }
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
    }
    else if(p_l2_node_old)
    {
         /*CTC_ERROR_GOTO(ctc_spool_remove(pl2_usw_master[lchip]->ad_spool, p_l2_node_old->adptr, NULL), ret, error_0);*/
        CTC_ERROR_GOTO(_sys_usw_l2_fdb_hash_remove(lchip, p_l2_node_old), ret, error_0);
        if (p_l2_node_old->rsv_ad)
        {
            mem_free(p_old_ad);
        }
        mem_free(p_l2_node_old);
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
    }
    /* write hw */
    CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &new_sys), ret, error_2);
    SYS_L2_DUMP_SYS_INFO(&new_sys);

    /*Note: MUST free old resource after write hardware*/
    if(p_old_ad && !old_rsv_ad)
    {
        CTC_ERROR_GOTO(_sys_usw_l2_dsmac_spool_remove(lchip, p_old_ad, NULL), ret, error_2);
    }
    else if (old_rsv_ad && p_old_ad)
    {
        mem_free(p_old_ad);
    }
    L2_UNLOCK;
    return ret;

error_2:
    if(!p_l2_node_old && p_l2_node)
    {
        _sys_usw_l2_fdb_hash_remove(lchip, p_l2_node);
    }
error_1:
    if(need_has_sw)
    {
        if (p_l2_node->rsv_ad)
        {
           mem_free(p_l2_node->adptr);
        }
        else
        {
            _sys_usw_l2_dsmac_spool_remove(lchip, &l2_ad, NULL);
        }
    }

error_0:
    if (bind_flag)
    {
        _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 0, 0, 0);
    }

    if(p_l2_node_old)
    {
        sal_memcpy(p_l2_node_old, &l2_node_old, sizeof(sys_l2_node_t));
        if (p_l2_node_old->bind_nh)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_l2_node_old, 1, 0, 0);
        }
    }

    if (!p_l2_node_old && p_l2_node)
    {
        mem_free(p_l2_node);
    }
    if (new_sys.ad_alloc)
    {
         sys_l2_ad_param_t l2_ad_param;
         sal_memset(&l2_ad_param,0,sizeof(sys_l2_ad_param_t));
         l2_ad_param.lchip = lchip;
        _sys_usw_l2_ad_spool_free_index(&l2_ad, &l2_ad_param);
    }

error_init:
    L2_UNLOCK;
    return ret;
}

int32
_sys_usw_l2_replace_match_fdb(uint8 lchip, ctc_l2_replace_t* p_replace)
{
    int32               ret = 0;
    uint32 cmd = 0;
    sys_l2_ad_t         l2_ad;
    uint8               bind_flag = 0;
    mac_lookup_result_t match_result = {0};
    ctc_l2_addr_t*     l2_addr = &p_replace->l2_addr;
    ctc_l2_addr_t*     match_addr = &p_replace->match_addr;
    uint8              with_nh = (p_replace->nh_id ? 1 : 0);
    uint32             nh_id   = p_replace->nh_id;
    sys_l2_info_t       new_sys;
    sys_l2_info_t       old_sys;
    uint32             match_key_index = 0;
    uint8              match_hit = 0;
    DsMac_m            old_dsmac;
    DsMac_m            dsmac;
    sys_l2_node_t       * p_l2_node = NULL;
    sys_l2_node_t       * p_match_node = NULL;
    uint8 old_is_logic = 0;
    uint8 old_is_dynamic = 0;
    uint8 mac_limit_en = 0;
    uint8 need_has_sw = 0;
    ctc_learning_action_info_t learning_action = {0};
    uint8 old_learning_disable = 0;

    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(match_addr->fid);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&new_sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&old_sys, 0, sizeof(sys_l2_info_t));

    if ((l2_addr->fid ==  DONTCARE_FID) || (match_addr->fid ==  DONTCARE_FID))
    {
        return CTC_E_NOT_SUPPORT;
    }
    L2_LOCK;
    CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_l2_fdb_check(lchip, l2_addr,with_nh, nh_id), pl2_usw_master[lchip]->l2_mutex)

     /*if hit or pending, remove hw first*/
    CTC_ERROR_GOTO(_sys_usw_l2_acc_lookup_mac_fid
        (lchip, match_addr->mac, match_addr->fid, &match_result), ret, error_0);
    if (match_result.hit || match_result.pending)
    {
         /*decode match key info*/
        uint8 index = 0;
        uint32 key_index = 0;
        uint8 cf_max = 0;
        sys_l2_calc_index_t calc_index;
        sal_memset(&old_dsmac, 0, sizeof(DsMac_m));
        sal_memset(&calc_index, 0, sizeof(sys_l2_calc_index_t));

        old_sys.key_index = match_result.key_index;
        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, match_result.ad_index, cmd, &old_dsmac), ret, error_0);
        CTC_ERROR_GOTO(_sys_usw_l2_build_sys_ad_info_by_index(lchip, match_result.ad_index, &old_sys), ret, error_0);
        match_key_index = match_result.key_index;
         /*check the hash equal*/
        CTC_ERROR_GOTO(_sys_usw_l2_fdb_calc_index(lchip, l2_addr->mac, l2_addr->fid, &calc_index, 0xFF), ret, error_0);
        cf_max = calc_index.index_cnt + MCHIP_CAP(SYS_CAP_L2_FDB_CAM_NUM);
        for (index = 0; index < cf_max; index++)
        {
            key_index = (index >= calc_index.index_cnt) ? (index - calc_index.index_cnt) : calc_index.key_index[index];
            if (match_key_index == key_index)
            {
                match_hit = 1;
                break;
            }
        }
        if (!match_hit)
        {
            ret = CTC_E_INVALID_CONFIG;
            goto  error_0;
        }

        p_match_node = _sys_usw_l2_fdb_hash_lkup(lchip, &match_addr->mac, match_addr->fid);

        old_is_logic = old_sys.is_logic_port;

        old_is_dynamic = (!CTC_FLAG_ISSET(old_sys.addr.l2_addr.flag,CTC_L2_FLAG_IS_STATIC) && old_sys.addr_type != SYS_L2_ADDR_TYPE_MC);

        mac_limit_en = (old_is_dynamic || pl2_usw_master[lchip]->static_fdb_limit)?1:0;

    }

    if (SYS_L2_IS_LOGIC_PORT(l2_addr->fid))
    {
        SYS_LOGIC_PORT_CHECK_WITH_UNLOCK(l2_addr->gport, pl2_usw_master[lchip]->l2_mutex);
    }

     /*map ctc to sys*/
    CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_UC, l2_addr, &new_sys, with_nh, nh_id), ret, error_0);

    /*build dsmac index*/
    CTC_ERROR_GOTO(_sys_usw_l2_get_reserved_index(lchip, &new_sys), ret, error_0);

    need_has_sw = !new_sys.rsv_ad_index || ((new_sys.use_destmap_profile||new_sys.ecmp_valid) && DRV_IS_DUET2(lchip));
    if(need_has_sw || p_match_node)
    {
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
    }
    if(need_has_sw)
    {
        sys_l2_ad_t*         p_ad = NULL;
        sal_memset(&l2_ad, 0, sizeof(l2_ad));
        MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node, sizeof(sys_l2_node_t));
        if(NULL == p_l2_node)
        {
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }

        sal_memcpy(&p_l2_node->mac, &l2_addr->mac, sizeof(mac_addr_t));
        p_l2_node->fid  = l2_addr->fid;
        p_l2_node->flag = l2_addr->flag;
        p_l2_node->ecmp_valid = new_sys.ecmp_valid;
        p_l2_node->use_destmap_profile = new_sys.use_destmap_profile;
        p_l2_node->aps_valid = new_sys.aps_valid;
        p_l2_node->nh_id = new_sys.nhid;
        p_l2_node->rsv_ad = new_sys.rsv_ad_index;

        if (new_sys.bind_nh)
        {
            /*do not using dsfwd, do nexthop and l2 bind*/
            ret = _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 1, 0, 0);
            if (CTC_E_IN_USE == ret)
            {
                /*nh have already bind, do unbind, using dsfwd*/
                CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, nh_id, &new_sys.fwd_ptr, 0, CTC_FEATURE_L2), ret, error_0);
                new_sys.merge_dsfwd = 0;
                new_sys.bind_nh = 0;
            }
            else if (ret < 0)
            {
                /*Bind fail, using dsfwd*/
                CTC_ERROR_GOTO(sys_usw_nh_get_dsfwd_offset(lchip, nh_id, &new_sys.fwd_ptr, 0, CTC_FEATURE_L2), ret, error_0);
                new_sys.merge_dsfwd = 0;
                new_sys.bind_nh = 0;
            }
            else
            {
                /*indicate bind success*/
                bind_flag = 1;
            }
        }

        if(new_sys.xdata_en)
        {
            CTC_ERROR_GOTO(_sys_usw_l2_xdata_check(lchip, &new_sys), ret, error_0);
        }

        CTC_ERROR_GOTO(_sys_usw_l2_encode_dsmac(lchip, &dsmac, &new_sys), ret, error_0);
        if (p_l2_node->rsv_ad)
        {
            MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node->adptr, sizeof(sys_l2_ad_t));
            if(NULL == p_l2_node->adptr)
            {
                ret = CTC_E_NO_MEMORY;
                goto error_0;
            }
            p_l2_node->adptr->index = new_sys.ad_index;
        }
        else if (!(new_sys.is_logic_port && CTC_FLAG_ISSET(new_sys.addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC)))
        {
            l2_ad.param.ldp = new_sys.use_lp? new_sys.addr.l2_addr.gport:0;
            if (new_sys.srv6_nh)
            {
                l2_ad.param.srv6_nhid = new_sys.nhid;
                l2_ad.param.ldp = SYS_COM_LDP_SRH_ID(new_sys.tunnel_id);
            }
            l2_ad.param.ds_mac = &dsmac;
            CTC_ERROR_GOTO(_sys_usw_l2_dsmac_spool_add(lchip, &l2_ad, &p_ad), ret, error_0);
            l2_ad.index = p_ad->index;
            p_l2_node->adptr = p_ad;
            new_sys.ad_index = p_ad->index;
        }
        else
        {
            l2_ad.index = new_sys.ad_index;
        }

        CTC_ERROR_GOTO(_sys_usw_l2_fdb_hash_add(lchip, p_l2_node), ret, error_1);
    }

    /* disable learning */
    sys_usw_learning_get_action(lchip, &learning_action);
    old_learning_disable = learning_action.value;
    if (0 == old_learning_disable)
    {
        learning_action.action = CTC_LEARNING_ACTION_MAC_TABLE_FULL;
        learning_action.value = 1;
        CTC_ERROR_GOTO(sys_usw_learning_set_action(lchip, &learning_action), ret, error_2);
    }

    /* remove old hw entry */
    if (match_hit)
    {
        CTC_ERROR_GOTO(sys_usw_l2_delete_hw_by_mac_fid
                        (lchip, match_addr->mac, match_addr->fid, mac_limit_en, old_is_logic, !old_is_dynamic), ret, error_3);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "Remove ucast fdb: key_index:0x%x, ad_index:0x%x\n",
                     match_result.key_index, match_result.ad_index);
    }

    /* write new hw */
    CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &new_sys), ret, error_4);

    SYS_L2_DUMP_SYS_INFO(&new_sys);

    /*remove old sw*/
    if(p_match_node)
    {
        if (p_match_node->bind_nh)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_match_node, 0, 0, 0);
        }
        _sys_usw_l2_fdb_hash_remove(lchip, p_match_node);
        if(p_match_node->adptr)
        {
            if (p_match_node->rsv_ad)
            {
                mem_free(p_match_node->adptr);
            }
            else
            {
                _sys_usw_l2_dsmac_spool_remove(lchip, p_match_node->adptr, NULL);
            }
        }
        mem_free(p_match_node);
    }
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "replace match hit:%d\n", match_hit);
    /* enable learning */
    if (0 == old_learning_disable)
    {
        learning_action.value = 0;
        learning_action.action = CTC_LEARNING_ACTION_MAC_TABLE_FULL;
        CTC_ERROR_RETURN_WITH_UNLOCK(sys_usw_learning_set_action(lchip, &learning_action), pl2_usw_master[lchip]->l2_mutex);
    }
    L2_UNLOCK;
    return CTC_E_NONE;

error_4:
    if (match_hit)
    {
        FDB_SET_MAC(old_sys.addr.l2_addr.mac, match_addr->mac);
        old_sys.addr.l2_addr.fid = match_addr->fid;
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, old_sys.ad_index, cmd, &old_dsmac);
        old_sys.rsv_ad_index = 1;
        CTC_ERROR_DUMP(_sys_usw_l2_write_hw(lchip, &old_sys));
    }
error_3:
    /* enable learning */
    if (0 == old_learning_disable)
    {
        learning_action.value = 0;
        learning_action.action = CTC_LEARNING_ACTION_MAC_TABLE_FULL;
        CTC_ERROR_DUMP(sys_usw_learning_set_action(lchip, &learning_action));
    }
error_2:
    if(p_l2_node)
    {
        _sys_usw_l2_fdb_hash_remove(lchip, p_l2_node);
    }
error_1:
    if(need_has_sw)
    {
        if (p_l2_node->rsv_ad)
        {
            mem_free(p_l2_node->adptr);
        }
        else
        {
            _sys_usw_l2_dsmac_spool_remove(lchip, &l2_ad, NULL);
        }
    }

error_0:
    if (bind_flag)
    {
        _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 0, 0, 0);
    }

    if (p_l2_node)
    {
        mem_free(p_l2_node);
    }
    if (new_sys.ad_alloc)
    {
        sys_l2_ad_param_t l2_ad_param;
        sal_memset(&l2_ad_param, 0, sizeof(sys_l2_ad_param_t));
        l2_ad_param.lchip = lchip;
        _sys_usw_l2_ad_spool_free_index(&l2_ad, &l2_ad_param);
    }
    L2_UNLOCK;
    return ret;
}

int32
sys_usw_l2_replace_fdb(uint8 lchip, ctc_l2_replace_t* p_replace)
{
    mac_lookup_result_t result = {0};
    uint8 is_same = 0;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_replace);
    SYS_L2UC_FID_CHECK(p_replace->l2_addr.fid);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s, fid:%d, flag:0x%x, gport:0x%x\n",
                      sys_output_mac(p_replace->l2_addr.mac), p_replace->l2_addr.fid,
                      p_replace->l2_addr.flag, p_replace->l2_addr.gport);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "match-mac:%s, match-fid:%d\n", sys_output_mac(p_replace->match_addr.mac), p_replace->match_addr.fid);

    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid
        (lchip, p_replace->l2_addr.mac, p_replace->l2_addr.fid, &result));

    /*if match.mac&&fid == l2_addr.mac&&fid, need add fdb*/
    is_same = (p_replace->l2_addr.fid == p_replace->match_addr.fid && !sal_memcmp(p_replace->l2_addr.mac, p_replace->match_addr.mac, CTC_ETH_ADDR_LEN)) ? 1 :0;

    if (result.hit || result.pending || is_same)
    {
        CTC_ERROR_RETURN(sys_usw_l2_add_fdb(lchip, &p_replace->l2_addr, p_replace->nh_id ? 1 : 0, p_replace->nh_id, 1));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_usw_l2_replace_match_fdb(lchip, p_replace));
    }

    return CTC_E_NONE;
}


int32
sys_usw_l2_remove_fdb(uint8 lchip, ctc_l2_addr_t* l2_addr)
{
    sys_l2_info_t       sys;
    mac_lookup_result_t rslt;
    sys_l2_node_t*      p_l2_node  = NULL;
    uint8               mac_limit_en = 0;
    int32               ret = CTC_E_NONE;
    uint8               is_logic = 0;
    uint8               is_dynamic = 0;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac: %s,fid: %d  \n",
                      sys_output_mac(l2_addr->mac),
                      l2_addr->fid);

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    sal_memcpy(&sys.addr.l2_addr, l2_addr, sizeof(ctc_l2_addr_t));

    if (l2_addr->fid ==  DONTCARE_FID)
    {
        return _sys_usw_l2_remove_tcam(lchip, l2_addr);
    }

    L2_LOCK;
    CTC_ERROR_GOTO(_sys_usw_l2_acc_lookup_mac_fid
                    (lchip, l2_addr->mac, l2_addr->fid, &rslt), ret, error_0);

    if (rslt.hit || rslt.pending)
    {
        sys.key_index = rslt.key_index;
        CTC_ERROR_GOTO(_sys_usw_l2_build_sys_ad_info_by_index(lchip, rslt.ad_index, &sys), ret, error_0);
        if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_REMOVE_DYNAMIC) && CTC_FLAG_ISSET(sys.addr.l2_addr.flag, CTC_L2_FLAG_IS_STATIC))
        {
            ret = CTC_E_NONE;
            goto error_0;
        }
    }
    else
    {
         /*SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n", sys_output_mac(l2_addr->mac), l2_addr->fid);*/
        ret =  CTC_E_NOT_EXIST;
        goto error_0;
    }

    is_logic = sys.is_logic_port;

    is_dynamic = (!CTC_FLAG_ISSET(sys.addr.l2_addr.flag,CTC_L2_FLAG_IS_STATIC) && sys.addr_type != SYS_L2_ADDR_TYPE_MC);

    mac_limit_en = (is_dynamic || pl2_usw_master[lchip]->static_fdb_limit)?1:0;
    p_l2_node = _sys_usw_l2_fdb_hash_lkup(lchip, &l2_addr->mac, l2_addr->fid);
    if(p_l2_node)
    {
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB, 1);
        /*No need to update port mac limit for logic port or ecmp*/
        is_logic = is_logic || p_l2_node->ecmp_valid;
    }
    /* remove hw entry */
    CTC_ERROR_GOTO(sys_usw_l2_delete_hw_by_mac_fid
                    (lchip, l2_addr->mac, l2_addr->fid, mac_limit_en, is_logic, !is_dynamic), ret, error_0);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Remove ucast fdb: key_index:0x%x, ad_index:0x%x\n",
                     rslt.key_index, rslt.ad_index);

    /* delete soft table*/
    if(p_l2_node)
    {
        if (p_l2_node->bind_nh)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 0, 0, 0);
        }

        CTC_ERROR_GOTO(_sys_usw_l2_fdb_hash_remove(lchip, p_l2_node), ret, error_0);
        if(p_l2_node->adptr)
        {
            if (p_l2_node->rsv_ad)
            {
                mem_free(p_l2_node->adptr);
            }
            else
            {
                CTC_ERROR_GOTO(_sys_usw_l2_dsmac_spool_remove(lchip, p_l2_node->adptr, NULL), ret, error_0);
            }
        }
        mem_free(p_l2_node);
    }

error_0:

    L2_UNLOCK;
    return ret;
}

/*only remove pending fdb */
int32
sys_usw_l2_remove_pending_fdb(uint8 lchip, ctc_l2_addr_t* l2_addr, uint32 ad_idx)
{
    mac_lookup_result_t rslt;
    int32               ret = 0;
    sys_l2_node_t* p_l2_node = NULL;

    SYS_L2_INIT_CHECK();

    sal_memset(&rslt, 0, sizeof(mac_lookup_result_t));

    L2_LOCK;

    CTC_ERROR_GOTO(_sys_usw_l2_acc_lookup_mac_fid
                    (lchip, l2_addr->mac, l2_addr->fid, &rslt), ret, error_0);

    if (!rslt.pending)
    {
        L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Not Pending,mac: %s,fid: %d  \n", sys_output_mac(l2_addr->mac), l2_addr->fid);
        return CTC_E_NONE;
    }

    if (rslt.ad_index != ad_idx)
    {
         L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Pending Aging But ad not match, should not remove mac: %s,fid: %d  ad_old:0x%x, ad_new:0x%x\n",
            sys_output_mac(l2_addr->mac), l2_addr->fid, ad_idx, rslt.ad_index);
        return CTC_E_NONE;
    }

    ret = sys_usw_l2_delete_hw_by_mac_fid(lchip, l2_addr->mac, l2_addr->fid, 1, SYS_L2_IS_LOGIC_PORT(l2_addr->fid), 0);
    p_l2_node = _sys_usw_l2_fdb_hash_lkup(lchip, &l2_addr->mac, l2_addr->fid);

    if(p_l2_node)
    {
        if (p_l2_node->bind_nh)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 0, 0, 0);
        }

        _sys_usw_l2_fdb_hash_remove(lchip, p_l2_node);
        if(p_l2_node->adptr)
        {
            if (p_l2_node->rsv_ad)
            {
                mem_free(p_l2_node->adptr);
            }
            else
            {
                _sys_usw_l2_dsmac_spool_remove(lchip, p_l2_node->adptr, NULL);
            }
        }
        mem_free(p_l2_node);
    }

error_0:

    L2_UNLOCK;
    return ret;
}

int32
sys_usw_l2_set_station_move(uint8 lchip, uint32 gport, uint8 type, uint32 logic_port, uint8 enable, uint32 value)
{
    uint32 cmd = 0;
    uint32 ad_index = 0;
    uint32 field_val = 0;
    ds_t ds;
    uint16 lport = 0;
    uint8  gchip = 0;
    uint8  is_local_chip = 0;
    uint8  station_move_mode = 0;
    uint8 is_lport = 0;
    SYS_L2_INIT_CHECK();

    SYS_GLOBAL_PORT_CHECK(gport);

    if (CTC_IS_LINKAGG_PORT(gport))
    {
        field_val = gport;
    }
    else
    {
        gchip = CTC_MAP_GPORT_TO_GCHIP(gport);
        SYS_GLOBAL_CHIPID_CHECK(gchip);
        lport = CTC_MAP_GPORT_TO_LPORT(gport);
        is_local_chip = sys_usw_chip_is_local(lchip, gchip);
        if (is_local_chip)
        {
            cmd = DRV_IOR(DsPhyPortExt_t, DsPhyPortExt_globalSrcPort_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &field_val));
        }
    }

    if (enable)
    {
    	if(pl2_usw_master[lchip]->vp_alloc_ad_en == 1)
    	{
        	SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
			return CTC_E_NOT_SUPPORT;
    	}
		ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT) + logic_port; /* logic_port */
    }
	else if (SYS_DRV_IS_LINKAGG_PORT(field_val) || CTC_IS_LINKAGG_PORT(gport))
    {

        ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK) + (field_val & CTC_LINKAGGID_MASK); /* linkagg */
    }
    else if (is_local_chip)
    {
        ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT) + lport; /* gport */
        is_lport= 1;
    }
    else if (pl2_usw_master[lchip]->rchip_ad_rsv[gchip])
    {
        CTC_ERROR_RETURN(_sys_usw_l2_get_rchip_reserved_ad(lchip, gchip, lport, &ad_index));
    }
    else
    {
        return CTC_E_NONE;
    }
    L2_LOCK;
    
    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, ad_index, cmd, &ds),pl2_usw_master[lchip]->l2_mutex);
    /* update ad */
    if (CTC_PORT_PROP_STATION_MOVE_PRIORITY == type && !pl2_usw_master[lchip]->station_move_no_learn)
    {
        sys_usw_global_get_station_move_mode(lchip, &station_move_mode);
        field_val = (value == 0 || station_move_mode) ? 1 : 0;
        SetDsMac(V, srcMismatchLearnEn_f, ds, field_val);
        SetDsMac(V, xAluEn_f, ds, station_move_mode && is_lport);
        SetDsMac(V, xAdEn_f, ds, station_move_mode && is_lport);
        if (station_move_mode && is_lport)
        {
            SetDsMac(V, auxData_f, ds, value);
        }
    }
    else if (CTC_PORT_PROP_STATION_MOVE_ACTION == type)
    {
       field_val = (value != CTC_PORT_STATION_MOVE_ACTION_TYPE_FWD) ? 1 : 0;
       SetDsMac(V, srcMismatchDiscard_f, ds, field_val);
    }
    
    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN_WITH_UNLOCK(DRV_IOCTL(lchip, ad_index, cmd, &ds),pl2_usw_master[lchip]->l2_mutex);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gchip:%d ad_index: 0x%x\n",gchip, ad_index);
    L2_UNLOCK;
    return CTC_E_NONE;
}

int32
sys_usw_l2_get_station_move(uint8 lchip, uint32 gport, uint8 type, uint32* value)
{
    uint32 cmd = 0;
    uint32 ad_index = 0;
    uint32 field_val = 0;
    uint16 lport = 0;
    uint8  gchip = 0;
    uint8  is_local_chip = 0;
    uint8 is_lport = 0;
    SYS_L2_INIT_CHECK();
    SYS_GLOBAL_PORT_CHECK(gport);

    if (CTC_IS_LINKAGG_PORT(gport))
    {
        field_val = gport;
    }
    else
    {
        gchip = CTC_MAP_GPORT_TO_GCHIP(gport);
        SYS_GLOBAL_CHIPID_CHECK(gchip);
        lport = CTC_MAP_GPORT_TO_LPORT(gport);
        is_local_chip = sys_usw_chip_is_local(lchip, gchip);
        if (is_local_chip)
        {
            cmd = DRV_IOR(DsPhyPortExt_t, DsPhyPortExt_globalSrcPort_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, &field_val));
        }
    }
    if (SYS_DRV_IS_LINKAGG_PORT(field_val) || CTC_IS_LINKAGG_PORT(gport))
    {
        ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK) + (field_val & CTC_LINKAGGID_MASK); /* linkagg */
    }
    else if (is_local_chip)
    {
        ad_index = sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT) + lport; /* gport */
        is_lport =1;
    }
    else if (pl2_usw_master[lchip]->rchip_ad_rsv[gchip])
    {
        CTC_ERROR_RETURN(_sys_usw_l2_get_rchip_reserved_ad(lchip, gchip, lport, &ad_index));
    }
    else
    {
        return CTC_E_NONE;
    }
    L2_LOCK;
    /* update ad */
    if (CTC_PORT_PROP_STATION_MOVE_PRIORITY == type)
    {   
        uint8 station_move_mode = 0;
        sys_usw_global_get_station_move_mode(lchip, &station_move_mode);
        cmd = DRV_IOR(DsMac_t, station_move_mode&&is_lport? DsMac_auxData_f : DsMac_srcMismatchLearnEn_f);
        CTC_ERROR_RETURN_WITH_UNLOCK(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &field_val),pl2_usw_master[lchip]->l2_mutex);
        *value = station_move_mode && is_lport? field_val : (field_val? 0 : 1);
    }
    else if (CTC_PORT_PROP_STATION_MOVE_ACTION == type)
    {
        cmd = DRV_IOR(DsMac_t, DsMac_srcMismatchDiscard_f);
        CTC_ERROR_RETURN_WITH_UNLOCK(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &field_val),pl2_usw_master[lchip]->l2_mutex);
        *value = field_val ? CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD : CTC_PORT_STATION_MOVE_ACTION_TYPE_FWD;
    }
    L2_UNLOCK;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_add_indrect(uint8 lchip, ctc_l2_addr_t* l2_addr, uint32 nhid, uint32 index)
{
    drv_acc_in_t  in;
    drv_acc_out_t out;
    sys_l2_info_t sys;
    DsMac_m ds_mac;
    uint32 cmd = 0;
    uint32 ad_index =0;
    DsFibHost0MacHashKey_m fdb_key;
    hw_mac_addr_t   hw_mac = {0};
    sys_nh_info_dsnh_t nhinfo;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s ,fid :%d ,flag:0x%x, gport:0x%x\n",
                      sys_output_mac(l2_addr->mac), l2_addr->fid, l2_addr->flag, l2_addr->gport);

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&ds_mac, 0, sizeof(DsMac_m));
    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    sys.addr_type = SYS_L2_ADDR_TYPE_UC;
    sys.is_logic_port = 1;
    sys.addr.l2_addr.gport = l2_addr->gport;
    sys.addr.l2_addr.policer_id = l2_addr->assign_port;   /*policer id*/
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nhid, &nhinfo, 0));
    sys.nh_ext = nhinfo.nexthop_ext;
    sys.dsnh_offset = nhinfo.dsnh_offset;
    sys.destmap = nhinfo.dest_map;
    sys.merge_dsfwd = 1;
    if (l2_addr->mask_valid)
    {
        sys.addr.l2_addr.mask_valid = 1;
    }
    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_SRC_DISCARD))
    {
        CTC_SET_FLAG(sys.addr.l2_addr.flag ,CTC_L2_FLAG_BIND_PORT);
    }
    else
    {
        CTC_UNSET_FLAG(sys.addr.l2_addr.flag ,CTC_L2_FLAG_BIND_PORT);
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "logic_port:0x%x, nhid:0x%x\n", l2_addr->gport, nhid);

    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(_sys_usw_l2_encode_dsmac(lchip, &ds_mac, &sys));
    ad_index = index;

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ad_index, cmd, &ds_mac));

    sal_memset(&in, 0, sizeof(in));
    sal_memset(&out, 0, sizeof(out));
    sal_memset(&fdb_key, 0, sizeof(DsFibHost0MacHashKey_m));

    FDB_SET_HW_MAC(hw_mac, l2_addr->mac);
    SetDsFibHost0MacHashKey(V, vsiId_f, &fdb_key, l2_addr->fid);
    SetDsFibHost0MacHashKey(A, mappedMac_f, &fdb_key, hw_mac);
    SetDsFibHost0MacHashKey(V, dsAdIndex_f, &fdb_key, ad_index);
    in.type = DRV_ACC_TYPE_ADD;
    in.tbl_id = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.data = &fdb_key;
    in.index = ad_index;
    CTC_BIT_SET(in.flag, DRV_ACC_ENTRY_DYNAMIC);
    CTC_BIT_SET(in.flag, DRV_ACC_UPDATE_MAC_LIMIT_CNT);
    CTC_BIT_SET(in.flag, DRC_ACC_PROFILE_MAC_LIMIT_EN);
    in.type = DRV_ACC_TYPE_ADD;
    in.op_type = DRV_ACC_OP_BY_KEY;

    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));
    if (out.is_conflict)
    {
        return CTC_E_FDB_HASH_CONFLICT;
    }

    if (CTC_FLAG_ISSET(l2_addr->flag, CTC_L2_FLAG_AGING_DISABLE))
    {
        CTC_ERROR_RETURN(sys_usw_aging_set_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, out.key_index, 0, 0));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_aging_set_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, out.key_index, 1, 1));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_remove_indrect(uint8 lchip, ctc_l2_addr_t* l2_addr)
{
    mac_lookup_result_t rslt;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac: %s,fid: %d  \n",
                      sys_output_mac(l2_addr->mac),
                      l2_addr->fid);

    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2_addr->mac, l2_addr->fid, &rslt));

    if (!rslt.hit && !rslt.pending)
    {
       return CTC_E_NOT_EXIST;
    }

    CTC_ERROR_RETURN(sys_usw_l2_delete_hw_by_mac_fid(lchip, l2_addr->mac, l2_addr->fid, 1, l2_addr->is_logic_port, 0));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "sync  ucast fdb: key_index:0x%x, ad_index:0x%x\n", rslt.key_index, rslt.ad_index);

    return CTC_E_NONE;
}

#define _REMOVE_GET_BY_INDEX_
/* index is key_index, not aging_ptr*/
int32
sys_usw_l2_remove_fdb_by_index(uint8 lchip, uint32 index)
{
    ctc_l2_addr_t l2_addr;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    SYS_L2_INDEX_CHECK(index);

    CTC_ERROR_RETURN(sys_usw_l2_get_fdb_by_index(lchip, index, &l2_addr, NULL));
    CTC_ERROR_RETURN(sys_usw_l2_remove_fdb(lchip, &l2_addr));

    return CTC_E_NONE;
}


int32
sys_usw_l2_get_fdb_by_index(uint8 lchip, uint32 key_index, ctc_l2_addr_t* l2_addr, sys_l2_detail_t* pi)
{
    uint32* p_flag;
    sys_l2_info_t     sys;
    drv_acc_in_t  in;
    drv_acc_out_t out;
    uint8         timer = 0;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2_INDEX_CHECK(key_index);

    in.type = DRV_ACC_TYPE_LOOKUP;
    in.tbl_id    = DsFibHost0MacHashKey_t;
    in.module= DRV_ACC_HASH_MODULE_FDB;
    in.index = key_index ;
    in.op_type = DRV_ACC_OP_BY_INDEX;
    CTC_ERROR_RETURN(drv_acc_api(lchip, &in, &out));

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    sys.key_index = key_index;
    _sys_usw_l2_decode_dskey(lchip, &sys, &out.data);

    if (!sys.key_valid)  /*not valid*/
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }

    /* decode and get gport, flag */
    _sys_usw_l2_build_sys_ad_info_by_index(lchip, sys.ad_index, &sys);
    p_flag = (sys.addr_type == SYS_L2_ADDR_TYPE_UC) ? &sys.addr.l2_addr.flag: &sys.addr.l2mc_addr.flag;
    CTC_ERROR_RETURN(sys_usw_aging_get_aging_timer(lchip, SYS_AGING_DOMAIN_MAC_HASH, key_index, &timer));
    if(timer == 0)
    {
        CTC_SET_FLAG((*p_flag), CTC_L2_FLAG_AGING_DISABLE);
    }
     /*_sys_usw_l2_unmap_flag(lchip, &l2_addr->flag, &sys.flag);*/

    sal_memcpy(l2_addr, &sys.addr.l2_addr, sizeof(ctc_l2_addr_t));

    if (sys.pending)
    {
        CTC_SET_FLAG(l2_addr->flag, CTC_L2_FLAG_PENDING_ENTRY);
    }
    if (pi)
    {
        pi->key_index   = key_index;
        pi->ad_index    = sys.ad_index;
        pi->flag        = (*p_flag);
        pi->pending     = sys.pending;
    }

    return CTC_E_NONE;
}

#define _HW_SYNC_UP_
    #if 0
/**
   @brief update soft tables after hardware learn aging
 */
int32
sys_usw_l2_sync_hw_info(uint8 lchip, void* pf)
{

    uint8                    index       = 0;
    sys_l2_info_t            sys;
    sys_learning_aging_data_t data;
    sys_learning_aging_info_t* p_info = NULL;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(pf);
    p_info = (sys_learning_aging_info_t*) pf;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Hw total_num  %d\n", p_info->entry_num);

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    for (index = 0; index < p_info->entry_num; index++)
    {
        sal_memcpy(&data, &(p_info->data[index]), sizeof(data));
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "   index  %d\n"\
                         "   mac [%s] \n"\
                         "   fid [%d] \n"\
                         "   is_aging  [%d]\n",
                         index,
                         sys_output_mac(data.mac),
                         data.fid,
                         data.is_aging);

        if (!data.is_hw)
        {
            continue;
        }

        if (data.is_aging)
        {
            _sys_usw_l2_build_sys_ad_info_by_index(lchip, data.ad_index, &sys);
            L2_LOCK;
#if 0
            if (pl2_usw_master[lchip]->cfg_has_sw)
            {
                p_l2_node = _sys_usw_l2_fdb_hash_lkup(lchip, data.mac, data.fid);
                if (!p_l2_node)
                {
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " lookup sw failed!!\n");
                    L2_UNLOCK;
                    continue;
                }

                FDB_ERR_RET_UL(_sys_usw_l2uc_remove_sw(lchip, p_l2_node));
                FDB_ERR_RET_UL(_sys_usw_l2_free_dsmac_index(lchip, &sys, NULL, &freed));

                if(freed)
                {
                    mem_free(p_l2_node->adptr);
                }
                mem_free(p_l2_node);
            }
#endif

            _sys_usw_l2_update_count(lchip, &sys.flag, -1, L2_COUNT_GLOBAL, &data.key_index);
            L2_UNLOCK;
        }
        else  /* learning */
        {
            if ((data.fid != 0) && (data.fid != 0xFFFF)
                && (!pl2_usw_master[lchip] || (data.fid >= pl2_usw_master[lchip]->cfg_max_fid)))
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "learning fid check failed ! ---continue---next one!\n");
                continue;
            }

            L2_LOCK;
#if 0
            if (pl2_usw_master[lchip]->cfg_has_sw)
            {
                p_l2_node = _sys_usw_l2_fdb_hash_lkup(lchip, data.mac, data.fid);
                if (p_l2_node) /* update  */
                {
                    /* update learning port */
                    ret = _sys_usw_l2_port_list_remove(lchip, p_l2_node);
                    if (ret < 0)
                    {
                        L2_UNLOCK;
                        continue;
                    }

                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "HW learning found old one: \n");
                    FDB_ERR_RET_UL(_sys_usw_l2_fdb_get_gport_by_adindex(lchip, data.ad_index, &(p_l2_node->adptr->gport), &is_logic));
                    p_l2_node->key.fid = data.fid;
                    FDB_SET_MAC(p_l2_node->key.mac, data.mac);
                    p_l2_node->key_index    = data.key_index;
                    p_l2_node->adptr->index = data.ad_index;
                    if (is_logic)
                    {
                        p_l2_node->adptr->flag.logic_port = 1;
                    }

                    FDB_ERR_RET_UL(_sys_usw_l2_port_list_add(lchip, p_l2_node));
                }
                else
                {
                    MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node, sizeof(sys_l2_node_t));
                    if (NULL == p_l2_node)
                    {
                        L2_UNLOCK;
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                        return CTC_E_NO_MEMORY;

                    }

                    FDB_ERR_RET_UL(_sys_usw_l2_fdb_get_gport_by_adindex(lchip, data.ad_index, &(p_l2_node->adptr->gport), &is_logic));
                    p_l2_node->key.fid = data.fid;
                    FDB_SET_MAC(p_l2_node->key.mac, data.mac);
                    p_l2_node->key_index    = data.key_index;
                    p_l2_node->adptr->index = data.ad_index;
                    if (is_logic)
                    {
                        p_l2_node->adptr->flag.logic_port = 1;
                    }
                    FDB_ERR_RET_UL(_sys_usw_l2uc_add_sw(lchip, p_l2_node));
                }
            }
#endif
            _sys_usw_l2_update_count(lchip, &sys.flag, 1, L2_COUNT_GLOBAL, &data.key_index);
            L2_UNLOCK;
        }
    }

    return CTC_E_NONE;
}
    #endif
#define _MC_DEFAULT_

/*this function is used by l2mc & l2 default entry*/
STATIC int32
_sys_at_l2_update_nh_by_port_bmp(uint8 lchip, void* nh_mc_p, void* mem)
{
    sys_nh_param_mcast_group_t* nh_mc = (sys_nh_param_mcast_group_t*) nh_mc_p;
    mc_mem_t* member = (mc_mem_t*) mem;
    uint8 i = 0;
    uint8 max_port_words = 0;
    uint8 mc_words = 0;

    if (DRV_TABLE_MAX_INDEX(lchip, DsMetEntrySlim1X_t))/*met_ext_mode = 1*/
    {
        nh_mc->mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_BITMAP;
        if (member->port_bmp[0] || member->port_bmp[1])
        {
            nh_mc->mem_info.l3if_type = 0;/*SYS_MET_VEC_SLIM_1X*/
            sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[0]), SYS_MC_BITMAP_WORDS*4);
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
        if (member->port_bmp[2] || member->port_bmp[3])
        {
            nh_mc->mem_info.l3if_type = 1;/*SYS_MET_VEC_SLIM_2X_0*/
            sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[0]), SYS_MC_BITMAP_WORDS*4);
            nh_mc->mem_info.pbm[0] = 0;
            nh_mc->mem_info.pbm[1] = 0;
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
        if (member->port_bmp[4] || member->port_bmp[5] || member->port_bmp[6] || member->port_bmp[7])
        {
            nh_mc->mem_info.l3if_type = 2;/*SYS_MET_VEC_SLIM_2X_1*/
            sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[4]), SYS_MC_BITMAP_WORDS*4);
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
        if (member->port_bmp[8] || member->port_bmp[9] || member->port_bmp[10] || member->port_bmp[11])
        {
            nh_mc->mem_info.l3if_type = 3;/*SYS_MET_VEC_SLIM_2X_2*/
            sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[8]), SYS_MC_BITMAP_WORDS*4);
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
        if (member->port_bmp[12] || member->port_bmp[13] || member->port_bmp[14] || member->port_bmp[15])
        {
            nh_mc->mem_info.l3if_type = 4;/*SYS_MET_VEC_SLIM_2X_3*/
            sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[12]), SYS_MC_BITMAP_WORDS*4);
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
    }
    else
    {
        if (MCHIP_CAP(SYS_CAP_NH_MC_PBMP_NUM) == MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP))
        {
            nh_mc->mem_info.l3if_type = SYS_MC_PORT_TYPE_4X;
            nh_mc->mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_BITMAP;
            sal_memcpy(nh_mc->mem_info.pbm, member->port_bmp, MCHIP_CAP(SYS_CAP_NH_MC_PBMP_NUM) >> 3);
            CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
        }
        else
        {
            max_port_words = (MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP) >> 5);/* 512 ports/32 bits */
            mc_words = (96 >> 5);/* 96 ports/32 bits */
            for (i = 0; i < (max_port_words / mc_words); i++)/*process SYS_MC_BITMAP_WORDS every time*/
            {
                if ((i < SYS_MC_PORT_TYPE_2X)
                    && (0 == member->port_bmp[i*mc_words])
                    && (0 == member->port_bmp[i*mc_words + 1])
                    && (0 == member->port_bmp[i*mc_words + 2]))
                {
                    continue;
                }
                else if ((i == SYS_MC_PORT_TYPE_2X)
                    && (0 == member->port_bmp[i*mc_words])
                    && (0 == member->port_bmp[i*mc_words + 1])
                    && (0 == member->port_bmp[i*mc_words + 2])
                    && (0 == member->port_bmp[i*mc_words + 3]))
                {
                    break;
                }
                nh_mc->mem_info.l3if_type = i;
                nh_mc->mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_BITMAP;
                sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[i*mc_words]), (i >= SYS_MC_PORT_TYPE_2X)? ((mc_words + 1) << 2) : (mc_words << 2));
                CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
            }
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_update_nh_by_port_bmp(uint8 lchip, void* nh_mc_p, void* mem)
{
    uint32 port_reflect_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
    sys_nh_param_mcast_group_t* nh_mc = (sys_nh_param_mcast_group_t*)nh_mc_p;
    mc_mem_t* member = (mc_mem_t*)mem;
    uint8 loop;
    uint8 i = 0;
    uint8 mc_words = 0;

    if (!DRV_FROM_TMM(lchip))
    {
        sys_usw_port_api_get_port_reflective(lchip, port_reflect_bmp);
    }

    mc_words = (MCHIP_CAP(SYS_CAP_MC_BITMAP_MAX_PORT) >> 5);/* 64 ports/32 bits */
    for (i = 0; i < (CTC_PORT_BITMAP_IN_WORD / mc_words); i++)/*process SYS_MC_BITMAP_WORDS every time*/
    {
        if(!DRV_FROM_TMM(lchip))
        {
            nh_mc->mem_info.pbm[0] = (port_reflect_bmp[i*mc_words] & member->port_bmp[i*mc_words]);
            nh_mc->mem_info.pbm[1] = (port_reflect_bmp[i*mc_words+1] & member->port_bmp[i*mc_words+1]);
            if(nh_mc->mem_info.pbm[0] || nh_mc->mem_info.pbm[1])
            {

                nh_mc->mem_info.is_src_port_check_dis = 1;
                nh_mc->mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_LOCAL;
                for(loop=0; loop < CTC_UINT32_BITS*2; loop++)
                {
                    if(!CTC_BMP_ISSET(nh_mc->mem_info.pbm, loop))
                    {
                        continue;
                    }
                    nh_mc->mem_info.destid = i*CTC_UINT32_BITS*2 + loop;
                    CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
                }
                member->port_bmp[i*mc_words] &= (~nh_mc->mem_info.pbm[0]);
                member->port_bmp[i*mc_words+1] &= (~nh_mc->mem_info.pbm[1]);
            }
        }
        if ((0 == member->port_bmp[i*mc_words])
            && (0 == member->port_bmp[i*mc_words + 1]))
        {
            continue;
        }
        nh_mc->mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_BITMAP;
        nh_mc->mem_info.is_src_port_check_dis = 0;
        nh_mc->mem_info.l3if_type = i;
        sal_memcpy(nh_mc->mem_info.pbm, &(member->port_bmp[i*mc_words]), (mc_words<<2));/*64bits*/
        CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, nh_mc));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_update_nh(uint8 lchip, uint16 group_id, mc_mem_t* member, uint8 is_add)
{
    int32                      ret        = CTC_E_NONE;
    uint8                      aps_brg_en = 0;
    uint8                      dest_chipid = 0;
    uint32                     m_nhid     = member->nh_id;
    uint32                     m_gport    = member->mem_port;
    uint8                      use_destmap_profile = 0;
    uint8                      is_assign = member->is_assign;
    uint8                      with_nh = member->with_nh;
    uint8                      xgpon_en = 0;
    uint32                     dest_id  = 0;

    sys_nh_param_mcast_group_t nh_mc;
    sal_memset(&nh_mc, 0, sizeof(nh_mc));

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

     /*mcast nexthop id*/
    CTC_ERROR_RETURN(sys_usw_nh_get_mcast_nh(lchip, group_id, &nh_mc.nhid));
    nh_mc.dsfwd_valid = 0;
    nh_mc.opcode      = is_add ? SYS_NH_PARAM_MCAST_ADD_MEMBER :
                        SYS_NH_PARAM_MCAST_DEL_MEMBER;

    if ((0 == with_nh) && (0 == member->port_bmp_en) && (0 == member->remote_chip))
    {
        if ((!CTC_IS_LINKAGG_PORT(member->mem_port))
            &&(!CTC_IS_CPU_PORT(member->mem_port))
            && sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(member->mem_port)))
        {
            uint16 lport = 0;
            lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(member->mem_port);
            member->port_bmp_en = (is_add || DRV_FROM_TMM(lchip))?1:0;
            sal_memset(member->port_bmp, 0, sizeof(ctc_port_bitmap_t));
            CTC_BMP_SET(member->port_bmp, lport);
            member->gchip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(member->mem_port);
        }
    }

    if (with_nh)
    {
        sys_nh_info_dsnh_t nh_info;
        sal_memset(&nh_info, 0, sizeof(nh_info));
        nh_mc.mem_info.ref_nhid    = m_nhid;

        if (is_add)
        {
            CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, m_nhid, &nh_info, 0), ret, error_0);

            if((nh_info.is_ecmp_intf &&  SYS_NH_TYPE_OVERLAY != nh_info.nh_entry_type && SYS_NH_TYPE_SRV6 != nh_info.nh_entry_type) || nh_info.ecmp_valid)
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR,"Mcast or vlan default entry not support ecmp member\n");
                goto error_1;
            }

            CTC_ERROR_GOTO(sys_usw_nh_get_port(lchip, m_nhid, &aps_brg_en, &dest_id), ret, error_0);
            if (aps_brg_en && (dest_id >= MCHIP_CAP(SYS_CAP_APS_GROUP_NUM)))
            {
                nh_mc.mem_info.is_mcast_aps = 1;
            }

            use_destmap_profile = nh_info.use_destmap_profile;
            if (aps_brg_en && is_assign)
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
                return CTC_E_NOT_SUPPORT;

            }
        }

        if(member->is_ul_nh)
        {
            sys_nh_info_dsnh_t nhinfo;
            sal_memset(&nhinfo, 0, sizeof(nhinfo));
            CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, member->mem_port, &nhinfo, 0));
            if(nhinfo.nh_entry_type != SYS_NH_TYPE_IPUC)
            {
                goto error_1;
            }
            dest_chipid =  CTC_MAP_GPORT_TO_GCHIP(nhinfo.gport);
            nh_mc.mem_info.destid = CTC_MAP_GPORT_TO_LPORT(nhinfo.gport);
            nh_mc.mem_info.ldp_ext = nhinfo.ldp_ext;
            nh_mc.mem_info.member_type = SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH_DESTID;
        }
        else if (is_assign)
        {
            /*Assign mode, dest id using user assign*/
            dest_chipid =  CTC_MAP_GPORT_TO_GCHIP(m_gport);
            nh_mc.mem_info.destid = CTC_MAP_GPORT_TO_LPORT(m_gport);
            nh_mc.mem_info.member_type = SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH_DESTID;
            use_destmap_profile = 0;
        }
        else
        {
            dest_chipid = CTC_MAP_GPORT_TO_GCHIP(dest_id);
            nh_mc.mem_info.destid = aps_brg_en?dest_id:CTC_MAP_GPORT_TO_LPORT(dest_id);
            nh_mc.mem_info.member_type = aps_brg_en ? SYS_NH_PARAM_BRGMC_MEM_LOCAL_WITH_APS_BRIDGE :
                                                      SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH;
        }
        sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if ((!DRV_IS_DUET2(lchip) && xgpon_en && member->mem_port))
        {
            nh_mc.mem_info.is_logic_port = 1;
            nh_mc.mem_info.logic_port = member->mem_port;
        }

    }
    else if (member->port_bmp_en)
    {
        dest_chipid = member->gchip_id;
    }
    else
    {
        if (!member->remote_chip)
        {
            SYS_GLOBAL_PORT_CHECK(m_gport);
        }

        dest_chipid =  member->remote_chip?((m_gport>>16)&0xff):CTC_MAP_GPORT_TO_GCHIP(m_gport);
        nh_mc.mem_info.destid =  member->remote_chip?(m_gport&0xffff):CTC_MAP_GPORT_TO_LPORT(m_gport);
        nh_mc.mem_info.member_type = member->remote_chip? SYS_NH_PARAM_MCAST_MEM_REMOTE : SYS_NH_PARAM_BRGMC_MEM_LOCAL;
    }

    if (!member->remote_chip && (aps_brg_en ||  CTC_LINKAGG_CHIPID == dest_chipid))
    {
        nh_mc.mem_info.is_linkagg = !aps_brg_en;
        nh_mc.mem_info.lchip = lchip;
        nh_mc.mem_info.is_destmap_profile = use_destmap_profile;
        CTC_ERROR_GOTO(sys_usw_mcast_nh_update(lchip, &nh_mc), ret, error_1);
    }
    else
    {
        sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if ((!xgpon_en) && (FALSE == sys_usw_chip_is_local(lchip, dest_chipid)) && (is_add ||
            nh_mc.mem_info.member_type != SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH))
        {
            ret = CTC_E_NONE;
            goto error_0;
        }

        nh_mc.mem_info.lchip      = lchip;
        nh_mc.mem_info.is_linkagg = 0;
        nh_mc.mem_info.is_destmap_profile = is_assign? 0: use_destmap_profile;
        if (member->port_bmp_en)
        {
            CTC_ERROR_GOTO(pl2_usw_master[lchip]->mcast_member_update_pbmp(lchip, &nh_mc, member), ret, error_1);
        }
        else
        {
            CTC_ERROR_GOTO(sys_usw_mcast_nh_update(lchip, &nh_mc), ret, error_1);
        }
    }

    return CTC_E_NONE;

 error_1:
    ret = CTC_E_INVALID_CONFIG;
 error_0:
    return ret;
}


STATIC int32
_sys_usw_l2_update_l2mc_nh(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr, uint8 is_add)
{
    mac_lookup_result_t rslt;
    int32 ret = 0;
    sys_l2_info_t  sys;
    mc_mem_t  mc_member;
    /*uint8 xgpon_en = 0;
    uint8 aps_brg_en = 0;
    uint32 dest_id    = 0*/;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2mc_addr);
    SYS_L2_FID_CHECK(l2mc_addr->fid);
    sal_memset(&sys, 0, sizeof(sys));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s,fid :%d, member_nd:%d, member_port:%d \n",
                      sys_output_mac(l2mc_addr->mac),
                      l2mc_addr->fid, l2mc_addr->member.nh_id, l2mc_addr->member.mem_port);

    if (CTC_FLAG_ISSET(l2mc_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT) && !(l2mc_addr->with_nh))
    {
        return CTC_E_INVALID_PARAM;
    }
    if(l2mc_addr->port_bmp_en && l2mc_addr->remote_chip)
    {
        return CTC_E_INVALID_PARAM;
    }
    L2_LOCK;

    ret = _sys_usw_l2_acc_lookup_mac_fid(lchip, l2mc_addr->mac, l2mc_addr->fid, &rslt);
    if (ret < 0)
    {
        L2_UNLOCK;
        return ret;
    }

    if (!rslt.hit)
    {
        L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }

    _sys_usw_l2_build_sys_ad_info_by_index(lchip, rslt.ad_index, &sys);

    if(sys.addr_type == SYS_L2_ADDR_TYPE_MC)
    {

        /*sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if (DRV_IS_DUET2(lchip) && xgpon_en)
        {
            if (l2mc_addr->with_nh)
            {
                FDB_ERR_RET_UL(sys_usw_nh_get_port(lchip, l2mc_addr->member.nh_id, &aps_brg_en, &dest_id));
                l2mc_addr->with_nh = 0;
                l2mc_addr->member.mem_port = dest_id;
            }
        }*/

        mc_member.is_assign = CTC_FLAG_ISSET(l2mc_addr->flag, CTC_L2_FLAG_ASSIGN_OUTPUT_PORT);
        mc_member.mem_port = l2mc_addr->member.mem_port;
        mc_member.nh_id = l2mc_addr->member.nh_id;
        mc_member.with_nh = l2mc_addr->with_nh;
        mc_member.remote_chip = l2mc_addr->remote_chip;
        mc_member.port_bmp_en = 0;
        if (l2mc_addr->port_bmp_en && (l2mc_addr->gchip_id != CTC_LINKAGG_CHIPID))
        {
            mc_member.port_bmp_en = 1;
            mc_member.gchip_id = l2mc_addr->gchip_id;
            sal_memcpy(mc_member.port_bmp, l2mc_addr->member.port_bmp, sizeof(ctc_port_bitmap_t));
        }
        else
        {
            sal_memset(mc_member.port_bmp, 0, sizeof(ctc_port_bitmap_t));
        }
        
        mc_member.is_ul_nh = (CTC_FLAG_ISSET(l2mc_addr->flag, CTC_L2_FLAG_ASSIGN_UL_NHID)) ? 1:0;
        L2_UNLOCK;
        return _sys_usw_l2_update_nh(lchip, sys.addr.l2mc_addr.l2mc_grp_id, &mc_member, is_add);
    }
    else
    {
        L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_update_default_nh(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr, uint8 is_add)
{
    sys_l2_fid_node_t * p_fid_node = NULL;
    mc_mem_t          mc_member;
    uint32 nhid = 0;
    uint32 fid_flag = 0;
    uint8 xgpon_en = 0;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2dflt_addr);
    SYS_L2_FID_CHECK(l2dflt_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "fid :%d \n", l2dflt_addr->fid);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "member port:0x%x\n", l2dflt_addr->member.mem_port);

    if(l2dflt_addr->port_bmp_en && l2dflt_addr->remote_chip)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_ASSIGN_OUTPUT_PORT) && !(l2dflt_addr->with_nh))
    {
        return CTC_E_INVALID_PARAM;
    }

    sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
    L2_LOCK;
    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, l2dflt_addr->fid);
    if (NULL == p_fid_node)
    {
        FDB_ERR_RET_UL(CTC_E_NOT_EXIST);
    }

    mc_member.is_assign = CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_ASSIGN_OUTPUT_PORT);
    mc_member.with_nh = l2dflt_addr->with_nh;
    mc_member.nh_id = l2dflt_addr->member.nh_id;
    mc_member.mem_port = l2dflt_addr->member.mem_port;

    if (!l2dflt_addr->with_nh)
    {
        fid_flag = _sys_usw_l2_get_fid_flag(lchip, l2dflt_addr->fid);
        if (CTC_FLAG_ISSET(fid_flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT))
        { 
            CTC_ERROR_RETURN_WITH_UNLOCK(_sys_usw_l2_get_nhid_by_logic_port(lchip, l2dflt_addr->member.mem_port, &nhid), pl2_usw_master[lchip]->l2_mutex);
            mc_member.with_nh = 1;
            mc_member.nh_id = nhid;
        }
    }
    if ((!DRV_IS_DUET2(lchip) && xgpon_en && mc_member.with_nh))
    {
        mc_member.mem_port = l2dflt_addr->logic_port;
    }
    mc_member.remote_chip = l2dflt_addr->remote_chip;
    mc_member.port_bmp_en = 0;
    if (l2dflt_addr->port_bmp_en && (l2dflt_addr->gchip_id != CTC_LINKAGG_CHIPID))
    {
        mc_member.port_bmp_en = 1;
        mc_member.gchip_id = l2dflt_addr->gchip_id;
        sal_memcpy(mc_member.port_bmp, l2dflt_addr->member.port_bmp, sizeof(ctc_port_bitmap_t));
    }
    else
    {
        sal_memset(mc_member.port_bmp, 0, sizeof(ctc_port_bitmap_t));
    }
    mc_member.is_ul_nh = (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_ASSIGN_UL_NHID)) ? 1:0;
    L2_UNLOCK;

    return _sys_usw_l2_update_nh(lchip, p_fid_node->mc_gid, &mc_member, is_add);
}
#if 0
STATIC int32
_sys_usw_l2mcast_remove_all_member(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
    return CTC_E_NOT_SUPPORT;

}
#endif
int32
sys_usw_l2mcast_add_member(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    return _sys_usw_l2_update_l2mc_nh(lchip, l2mc_addr, 1);
}
int32
sys_usw_l2mcast_remove_member(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    return _sys_usw_l2_update_l2mc_nh(lchip, l2mc_addr, 0);
}

int32
sys_usw_l2mcast_add_addr(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr)
{
    sys_nh_param_mcast_group_t nh_mcast_group;

    int32                      ret     = CTC_E_NONE;
    mac_lookup_result_t        result;
    sys_l2_info_t              new_sys;
    sys_l2_node_t*      p_l2_node_old = NULL;
    sys_l2_info_t       old_sys;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2mc_addr);

    SYS_L2_FID_CHECK(l2mc_addr->fid);
    SYS_USW_CID_CHECK(lchip,l2mc_addr->cid);
    if (l2mc_addr->service_id >= MCHIP_CAP(SYS_CAP_SERVICE_ID_NUM))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (l2mc_addr->cid && l2mc_addr->service_id)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " FDB can not support cid and service_id at the same time\n");
        return CTC_E_NOT_SUPPORT;
    }

    if (SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_L2MC) <= pl2_usw_master[lchip]->l2mc_count)
    {
        return CTC_E_NO_RESOURCE;
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s, fid :%d, l2mc_group_id: %d  \n",
                      sys_output_mac(l2mc_addr->mac),
                      l2mc_addr->fid,
                      l2mc_addr->l2mc_grp_id);

    sal_memset(&new_sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&old_sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&nh_mcast_group, 0, sizeof(sys_nh_param_mcast_group_t));

    L2_LOCK;
     /*  lookup hw, check result*/
    CTC_ERROR_GOTO(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2mc_addr->mac, l2mc_addr->fid, &result), ret, error_0);
    if (result.conflict)
    {
        ret = CTC_E_HASH_CONFLICT;
        goto error_0;
    }

    if(result.hit)
    {
        p_l2_node_old = _sys_usw_l2_fdb_hash_lkup(lchip, &l2mc_addr->mac, l2mc_addr->fid);
        CTC_ERROR_GOTO(_sys_usw_l2_build_sys_ad_info_by_index(lchip, result.ad_index, &old_sys), ret, error_0);
        if(!l2mc_addr->share_grp_en || p_l2_node_old || SYS_L2_ADDR_TYPE_MC != old_sys.addr_type)
        {
            ret = CTC_E_EXIST;
            goto error_0;
        }
    }

    new_sys.is_exist = result.hit;

    CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_MC, l2mc_addr, &new_sys, 0, 0), ret, error_0);

    if (l2mc_addr->share_grp_en)
    {
        CTC_ERROR_GOTO(sys_usw_nh_get_mcast_nh(lchip, l2mc_addr->l2mc_grp_id, &nh_mcast_group.nhid), ret, error_0);
    }
    else
    {
        CTC_ERROR_GOTO(sys_usw_mcast_nh_create(lchip, l2mc_addr->l2mc_grp_id, &nh_mcast_group), ret, error_0);
    }

    if (result.hit)
    {
        new_sys.ad_index = result.ad_index;
    }
    else
    {
        CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, 1<<31|DsMac_t, 1, 1, 1, &new_sys.ad_index), ret, error_1);
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);
    }

    /* CTC_ERROR_GOTO(_sys_usw_l2_mc2nhop_add(lchip, l2mc_addr->l2mc_grp_id, nh_mcast_group.nhid),ret, error_2);*/

     /*4. write hw*/
     CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &new_sys), ret, error_2);

     SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Add mcast fdb: chip_id:%d, key_index:0x%x, ad_index:0x%x, nexthop_id:0x%x, ds_fwd_offset:0x%x\n",
                         lchip, new_sys.key_index, (uint32) new_sys.ad_index, nh_mcast_group.nhid, new_sys.fwd_ptr);

    if (!result.hit)
    {
        /* 5. update index*/
        pl2_usw_master[lchip]->l2mc_count += 1;
    }

    L2_UNLOCK;
    return ret;

     /*_sys_usw_l2_mc2nhop_remove(lchip, l2mc_addr->l2mc_grp_id);*/
 error_2:
    if(!result.hit)
    {
        sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, new_sys.ad_index);
    }
 error_1:
    if(!l2mc_addr->share_grp_en)
    {
        sys_usw_mcast_nh_delete(lchip, nh_mcast_group.nhid);
    }
 error_0:
    L2_UNLOCK;
    return ret;
}


int32
sys_usw_l2mcast_remove_addr(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr)
{
    sys_l2_info_t       sys;
    mac_lookup_result_t rslt;
    uint32 nhp_id = 0;
    int32 ret = CTC_E_NONE;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2mc_addr);
    SYS_L2_FID_CHECK(l2mc_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac:%s,fid :%d  \n",
                      sys_output_mac(l2mc_addr->mac),
                      l2mc_addr->fid);


    sal_memset(&sys, 0, sizeof(sys_l2_info_t));

    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2mc_addr->mac, l2mc_addr->fid, &rslt));

    if (rslt.hit)
    {
        _sys_usw_l2_build_sys_ad_info_by_index(lchip, rslt.ad_index, &sys);
    }
    else
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }

    L2_LOCK;
    if(sys.addr_type == SYS_L2_ADDR_TYPE_MC)
    {
        sys_usw_nh_get_mcast_nh(lchip, sys.addr.l2mc_addr.l2mc_grp_id, &nhp_id);
    }
    else
    {
        L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }

    if (CTC_FLAG_ISSET(l2mc_addr->flag, CTC_L2_FLAG_KEEP_EMPTY_ENTRY))
    {
        L2_UNLOCK;
        sys_usw_nh_remove_mcast_all_members_api(lchip, nhp_id);
        return CTC_E_NONE;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);
    /* remove hw entry */
    ret = sys_usw_l2_delete_hw_by_mac_fid(lchip, l2mc_addr->mac, l2mc_addr->fid, 0xFF,0,0);
    if (ret)
    {
        L2_UNLOCK;
        return ret;
    }
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Remove mcast fdb: key_index:0x%x, ad_index:0x%x\n",
                    rslt.key_index, rslt.ad_index);

    /* must lookup success. */
    if(0 != nhp_id)
    {
        if (!sys.share_grp_en)
        {
            /* remove sw entry */
            sys_usw_mcast_nh_delete(lchip, nhp_id);
        }
        sys_usw_ftm_free_table_offset(lchip, 1<<31|DsMac_t, 1, 1, rslt.ad_index);

    }
    else
    {
        if (!sys.share_grp_en)
        {
            L2_UNLOCK;
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
            return CTC_E_NOT_EXIST;
        }
        else
        {
            sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, rslt.ad_index);
        }
    }

    pl2_usw_master[lchip]->l2mc_count--;
    L2_UNLOCK;
    return CTC_E_NONE;
}

int32
sys_usw_l2_add_port_to_default_entry(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    return _sys_usw_l2_update_default_nh(lchip, l2dflt_addr, 1);
}

int32
sys_usw_l2_remove_port_from_default_entry(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    return _sys_usw_l2_update_default_nh(lchip, l2dflt_addr, 0);
}

int32
sys_usw_l2_add_default_entry(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    sys_l2_info_t              sys;
    int32                      ret     = CTC_E_NONE;
    sys_nh_param_mcast_group_t nh_mcast_group;
    sys_l2_fid_node_t          * p_fid_node = NULL;
    uint32                     nh_id = 0;
    uint32                     max_ex_nhid = 0;
    int32 ret_error = CTC_E_NONE;
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2dflt_addr);
    SYS_L2_FID_CHECK(l2dflt_addr->fid);
    SYS_USW_CID_CHECK(lchip,l2dflt_addr->cid);

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    sal_memset(&nh_mcast_group, 0, sizeof(sys_nh_param_mcast_group_t));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "fid :%d ,l2mc_grp_id:%d \n", l2dflt_addr->fid, l2dflt_addr->l2mc_grp_id);

    if (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_UNKOWN_UCAST_DROP))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
  /* not support. */
    }

    if (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_UNKOWN_MCAST_DROP))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
  /* not support. */
    }

    if (!DRV_FROM_AT(lchip) && NULL != l2dflt_addr->xdata)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
    }

    if (DRV_FROM_TMM(lchip) && (l2dflt_addr->cid > SYS_DEFAULT_ENTRY_MAX_CID))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "categoryId is out of range!  categoryId = %d\n", l2dflt_addr->cid);
        return CTC_E_INVALID_PARAM;
    }

    L2_LOCK;
    CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_DF, l2dflt_addr, &sys, 0, 0), ret, error_0);

    sys.ad_index = DEFAULT_ENTRY_INDEX(l2dflt_addr->fid);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "build hash mcast ad_index:0x%x\n", sys.ad_index);

    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, l2dflt_addr->fid);
    if (NULL == p_fid_node)
    {
        MALLOC_ZERO(MEM_FDB_MODULE, p_fid_node, sizeof(sys_l2_fid_node_t));
        if (!p_fid_node)
        {
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }

        /* 1,create mcast group */
        if(l2dflt_addr->share_grp_en)
        {
            CTC_ERROR_GOTO(sys_usw_nh_get_mcast_nh(lchip, l2dflt_addr->l2mc_grp_id, &nh_id), ret, error_1);
            sys_usw_nh_get_max_external_nhid(lchip, &max_ex_nhid);
            if (nh_id >= max_ex_nhid)
            {
                ret = CTC_E_NOT_SUPPORT;
                goto  error_1;
            }
        }
        else
        {
            ret_error = sys_usw_mcast_nh_create(lchip, l2dflt_addr->l2mc_grp_id, &nh_mcast_group);
            CTC_ERROR_GOTO(ret_error, ret, error_1);
        }

        /* map fid node.*/
        p_fid_node->fid    = l2dflt_addr->fid;
        p_fid_node->flag   = l2dflt_addr->flag;
        p_fid_node->mc_gid = l2dflt_addr->l2mc_grp_id;
        p_fid_node->share_grp_en = l2dflt_addr->share_grp_en;
        p_fid_node->cid = l2dflt_addr->cid;
        p_fid_node->xdata_en = sys.xdata_en;
        ret                = ctc_vector_add(pl2_usw_master[lchip]->fid_vec, l2dflt_addr->fid, p_fid_node);
        if (!ret)
        {
            ret = CTC_E_NO_MEMORY;
            goto error_2;
        }
    }
    else
    {
        if(p_fid_node->mc_gid != l2dflt_addr->l2mc_grp_id)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "default entry has been created, l2mc group id cann't be changed\n");
            ret = CTC_E_EXIST;
        }
        else
        {
            ret = CTC_E_NONE;  /* already created. */

        }
        goto error_0;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE, 1);
    /* write hw */
    ret = _sys_usw_l2_write_hw(lchip, &sys);
    if (FAIL(ret))
    {
        goto error_3;
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Add default entry: chip_id:%d, ad_index:0x%x, group_id: 0x%x\n", lchip, sys.ad_index,
                         sys.addr.l2df_addr.l2mc_grp_id);

    pl2_usw_master[lchip]->def_count++;
    L2_UNLOCK;
    return CTC_E_NONE;

 error_3:
    ctc_vector_del(pl2_usw_master[lchip]->fid_vec, l2dflt_addr->fid);
 error_2:
    if (!p_fid_node->share_grp_en)
    {
        sys_usw_mcast_nh_delete(lchip, nh_mcast_group.nhid);
    }
 error_1:
    mem_free(p_fid_node);
 error_0:
    L2_UNLOCK;
    return ret;
}


int32
sys_usw_l2_remove_default_entry(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    sys_l2_fid_node_t * p_fid_node = NULL;
    sys_l2_info_t     sys;
    int32             ret = 0;
    uint32            nh_id = 0;
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2dflt_addr);
    SYS_L2_FID_CHECK(l2dflt_addr->fid);

    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "fid :%d  \n", l2dflt_addr->fid);

    L2_LOCK;

    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, l2dflt_addr->fid);
    if (NULL == p_fid_node)
    {
        ret = CTC_E_NOT_EXIST;
        goto error_0;
    }

    sys.ad_index          = DEFAULT_ENTRY_INDEX(l2dflt_addr->fid);
    sys.addr_type  = SYS_L2_ADDR_TYPE_DEFAULT;
    sys.revert_default    = 1;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE, 1);
    /* remove hw */
    CTC_ERROR_GOTO(_sys_usw_l2_write_hw(lchip, &sys), ret, error_0);
    CTC_ERROR_GOTO(sys_usw_nh_get_mcast_nh(lchip, p_fid_node->mc_gid, &nh_id), ret, error_0);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Remove default entry: chip_id:%d, ad_index:0x%x nexthop_id 0x%x\n" \
                                            , lchip, DEFAULT_ENTRY_INDEX(p_fid_node->fid), nh_id);
    if (!p_fid_node->share_grp_en)
    {
        sys_usw_mcast_nh_delete(lchip, nh_id);
    }
    /* remove sw*/
    ctc_vector_del(pl2_usw_master[lchip]->fid_vec, p_fid_node->fid);
    mem_free(p_fid_node);

    pl2_usw_master[lchip]->def_count--;
 error_0:
    L2_UNLOCK;
    return ret;
}

#define _FDB_SHOW_


int32
sys_usw_l2_show_status(uint8 lchip)
{
    uint32 ad_cnt = 0;
    uint32 rsv_ad_num = 0;
    uint32 fdb_num = 0;
    uint32 running_num = 0;
    uint32 dynamic_running_num = 0;
    uint32 cmd = 0;
    ctc_l2_fdb_query_t query;
    MacLimitSystem_m mac_limit_system;
    MacLimitSystemCount_m mac_limit_system_cnt;
    uint32 alloc_ad_cnt = 0;
    uint16  loop1 = 0;
    uint16  loop2 = 0;
    uint16 used_count = 0;
    uint32 * fwd_pbm = NULL;
    int32 rsv_port_ad_num = 0;

    SYS_L2_INIT_CHECK();
    lchip = SYS_PP_BASE(lchip);

    fwd_pbm = sys_usw_chip_get_fwd_pbm(lchip);
    sal_memset(&query, 0, sizeof(ctc_l2_fdb_query_t));
    sal_memset(&mac_limit_system, 0, sizeof(MacLimitSystem_m));
    sal_memset(&mac_limit_system_cnt, 0, sizeof(MacLimitSystemCount_m));

    sys_usw_ftm_query_table_entry_num(lchip, DsMac_t, &ad_cnt);
    CTC_BMP_COUNT_RANGE(fwd_pbm, rsv_port_ad_num, 0, SYS_USW_MAX_PORT_NUM_PER_CHIP);
    rsv_ad_num = SYS_USW_MAX_LINKAGG_GROUP_NUM + rsv_port_ad_num + (pl2_usw_master[lchip]->cfg_max_fid+1);

    if (!pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        rsv_ad_num += pl2_usw_master[lchip]->cfg_vport_num;
    }

    fdb_num = sys_usw_ftm_get_spec(lchip, CTC_FTM_SPEC_MAC);

    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOR(MacLimitSystemCount_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &mac_limit_system_cnt));
        running_num = GetMacLimitSystemCount(V, profileRunningCount_f, &mac_limit_system_cnt);
        dynamic_running_num = GetMacLimitSystemCount(V, dynamicRunningCount_f, &mac_limit_system_cnt);
    }
    else
    {
        cmd = DRV_IOR(MacLimitSystem_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &mac_limit_system));
        running_num = GetMacLimitSystem(V, profileRunningCount_f, &mac_limit_system);
        dynamic_running_num = GetMacLimitSystem(V, dynamicRunningCount_f, &mac_limit_system);
    }

     /*get alloc ad count*/
    sys_usw_ftm_get_alloced_table_count(lchip, DsMac_t, &alloc_ad_cnt);
    L2_LOCK;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------Work Mode---------------------\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6s \n", "Hardware Learning", pl2_usw_master[lchip]->cfg_hw_learn?"Y":"N");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "L2 software db count", pl2_usw_master[lchip]->fdb_hash->count);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------L2 FDB Resource---------------------\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Key Resource:\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Total Key count", fdb_num);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Used Key count", running_num+pl2_usw_master[lchip]->l2mc_count);


    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--Static", running_num-dynamic_running_num);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--Dynamic", dynamic_running_num);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--L2MC", pl2_usw_master[lchip]->l2mc_count);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Ad Resource:\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Total Ad count", ad_cnt);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Used Ad count", alloc_ad_cnt);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--Reserved ", rsv_ad_num);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%3u(%u) \n", "--Drop(index)", 1, pl2_usw_master[lchip]->ad_index_drop);


    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--Dynamic", alloc_ad_cnt-rsv_ad_num-1);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Ad Base:\n");
    if (!pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:0x%-4x \n", "Logic Port", sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT));
    }
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:0x%-4x \n", "Port", sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:0x%-4x \n", "Linkagg", sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:0x%-4x \n", "Default Entry", pl2_usw_master[lchip]->dft_entry_base);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Other Resource:\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Default entry count", pl2_usw_master[lchip]->def_count);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "FID Number", pl2_usw_master[lchip]->cfg_max_fid+1);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "Logic Port Number", pl2_usw_master[lchip]->cfg_vport_num);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "BlackHole Resource:\n")
    for(loop1=0; loop1<SYS_L2_MAX_BLACK_HOLE_ENTRY/32; loop1++)
    {
        for(loop2=0; loop2 < 32; loop2++)
        {
            if(CTC_IS_BIT_SET(pl2_usw_master[lchip]->mac_fdb_bmp[loop1], loop2))
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "----key index", loop1*32 + loop2);
                used_count++;
            }
        }
    }
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-30s:%6u \n", "--Total entry count", used_count);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

     L2_UNLOCK;
    return CTC_E_NONE;
}

int32
sys_usw_l2_dump_default_entry(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    uint32 nh_id                  = 0;
    sys_l2_fid_node_t* p_fid_node = NULL;

    SYS_L2_INIT_CHECK();

    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, l2dflt_addr->fid);
    if (NULL == p_fid_node)
    {
        CTC_ERROR_RETURN(CTC_E_NOT_EXIST);
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_mcast_nh(lchip, p_fid_node->mc_gid, &nh_id));
    sys_usw_nh_dump(lchip, nh_id, FALSE);
    return CTC_E_NONE;
}

int32
sys_usw_l2_dump_all_default_entry(uint8 lchip)
{
    sys_l2_fid_node_t* p_fid_node = NULL;
    uint16 fid = 0;
    uint16 pre_entry = 0;
    uint16 last_entry = 0;
    uint8 first_flag = 0;
    uint8 find_first = 0;
    uint8 seq_flag = 0;
    uint16 count = 0;
    uint16 block_cnt = 0;
    char buf[20] = {0};
    char tmp_buf[10] = {0};

    SYS_L2_INIT_CHECK();

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Fid list:\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "------------------------------------------------------------\n");

    for (fid = 1; fid <= pl2_usw_master[lchip]->cfg_max_fid; fid++)
    {
        p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, fid);
        if (NULL == p_fid_node)
        {
            continue;
        }

        count++;
        last_entry = fid;

        if (find_first == 0)
        {
            first_flag = 1;
        }

        if (first_flag)
        {
            sal_sprintf(buf, "%d",fid);
            find_first = 1;
            first_flag = 0;
            pre_entry = fid;
        }
        else
        {
            /*current fid is not sequenced by last*/
            if (fid != (pre_entry+1))
            {
                /*already have sequence fid list*/
                if (seq_flag)
                {
                    /*print last entry, and seperate remark*/
                    sal_sprintf(tmp_buf, "%d,",pre_entry);
                    sal_strcat((char*)buf, (char*)tmp_buf);
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s ", (char*)buf);
                    block_cnt++;
                    if ((block_cnt%6) == 0)
                    {
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
                    }
                    /*print seperate remark and current fid*/
                    sal_sprintf(buf, "%d",fid);
                }
                else
                {
                    /*print seperate remark and current fid*/
                    sal_strcat((char*)buf, ",");
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s ", (char*)buf);
                    block_cnt++;

                    if ((block_cnt%6) == 0)
                    {
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
                    }
                    sal_sprintf(buf, "%d",fid);
                }

                seq_flag = 0;
            }
            else
            {
                /*already have sequence fid list*/
                if (seq_flag)
                {
                    /*do nothing*/
                }
                else
                {
                    sal_strcat((char*)buf, "~");
                    seq_flag = 1;
                }
            }

            pre_entry = fid;
        }
    }

    if (seq_flag)
    {
        sal_sprintf(tmp_buf, "%d",last_entry);
        sal_strcat((char*)buf, (char*)tmp_buf);
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s ", (char*)buf);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Total Count:%d\n", count);

    return CTC_E_NONE;
}

int32
sys_usw_l2_dump_l2mc_entry(uint8 lchip, ctc_l2_mcast_addr_t* l2mc_addr, bool detail)
{
    mac_lookup_result_t rslt;
    sys_l2_info_t       sys;
    uint32              nhp_id = 0;

    SYS_L2_INIT_CHECK();

    sal_memset(&rslt, 0, sizeof(mac_lookup_result_t));
    sal_memset(&sys, 0, sizeof(sys_l2_info_t));
    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2mc_addr->mac, l2mc_addr->fid, &rslt));

    if (rslt.hit)
    {
        _sys_usw_l2_build_sys_ad_info_by_index(lchip, rslt.ad_index, &sys);
    }
    else
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    L2_LOCK;

    if(sys.addr_type == SYS_L2_ADDR_TYPE_MC)
    {
         /*_sys_usw_l2_get_nhop_by_mc_grp_id(lchip, sys.mc_gid, &nhp_id);*/
        sys_usw_nh_get_mcast_nh(lchip, sys.addr.l2mc_addr.l2mc_grp_id, &nhp_id);
    }
    else
    {
        L2_UNLOCK;
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    L2_UNLOCK;

    sys_usw_nh_dump(lchip, nhp_id, detail);
    return CTC_E_NONE;
}


int32
sys_usw_l2_get_default_entry_features(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    sys_l2_fid_node_t* p_fid_node = NULL;
    int32            ret          = 0;
    uint16           fid = 0;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2dflt_addr);
    SYS_L2_FID_CHECK(l2dflt_addr->fid);

    fid = l2dflt_addr->fid;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "fid :%d\n", fid);

    L2_LOCK;

    p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, fid);
    if (NULL == p_fid_node)
    {
        ret = CTC_E_NOT_EXIST;
        goto error_0;
    }

    l2dflt_addr->flag        = p_fid_node->flag;
    l2dflt_addr->fid         = p_fid_node->fid;
    l2dflt_addr->l2mc_grp_id = p_fid_node->mc_gid;
    l2dflt_addr->cid         = p_fid_node->cid;
    l2dflt_addr->share_grp_en = p_fid_node->share_grp_en;

    if(l2dflt_addr->xdata && p_fid_node->xdata_en)
    {
        DsMac_m dsmacdefault;
        uint32 value[3] = {0};
        uint32 cmd = 0;
        uint8 num = 0;
        if (!DRV_FROM_AT(lchip))
        {
            ret = CTC_E_NOT_SUPPORT;
            goto error_0;
        }
        l2dflt_addr->xdata->prof_id = SYS_DFT_XDATA_PROFILE_ID;
        l2dflt_addr->xdata->type = CTC_XDATA_PROF_TYPE_DSMACDA;

        CTC_ERROR_GOTO(MCHIP_XDATA(lchip)->prof_get_info(lchip, l2dflt_addr->xdata, 0), ret, error_0);            

        cmd = DRV_IOR(DsMacDefault_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, DEFAULT_ENTRY_INDEX(l2dflt_addr->fid), cmd, &dsmacdefault), ret, error_0);
        GetDsMacDefault(A, xAdData_f, &dsmacdefault, value);

        for(num = 0; num < l2dflt_addr->xdata->num; num++)
        {
            SYS_USW_GET_XDATA(l2dflt_addr->xdata->fields[num].width, l2dflt_addr->xdata->fields[num].offset, l2dflt_addr->xdata->fields[num].data, value);
        }
    }
 error_0:
    L2_UNLOCK;
    return ret;
}

int32
sys_usw_l2_set_nhid_by_logic_port(uint8 lchip, uint16 logic_port, uint32 nhp_id)
{
    int32 ret= 0;

    SYS_L2_INIT_CHECK();
    SYS_LOGIC_PORT_CHECK(logic_port);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    L2_LOCK;
    if(0 == nhp_id)
    {
        ret = _sys_usw_l2_unbind_nhid_by_logic_port(lchip, logic_port);
    }
    else
    {
        ret =_sys_usw_l2_bind_nhid_by_logic_port(lchip, logic_port, nhp_id);
    }
    L2_UNLOCK;
    return ret;
}



#define FDB_LOGIC_PORT_VEC_B    1024
#define FDB_MAC_FID_HASH_SIZE   4096
#define FDB_MAC_NHID_HASH_SIZE  8192
#define FDB_MAC_FID_HASH_B      64
#define FDB_DFT_HASH_B          64

bool
sys_usw_l2_fdb_trie_sort_en(uint8 lchip)
{
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (pl2_usw_master[lchip] && pl2_usw_master[lchip]->trie_sort_en)
    {
        return TRUE;
    }

    return FALSE;
}
/**internal test**/
int32
sys_usw_l2_fdb_set_trie_sort(uint8 lchip, uint8 enable)
{
    SYS_L2_INIT_CHECK();

    pl2_usw_master[lchip]->trie_sort_en = enable;

    return CTC_E_NONE;
}

int32
sys_usw_l2_set_static_mac_limit(uint8 lchip, uint8 static_limit_en)
{

    SYS_L2_INIT_CHECK();
    pl2_usw_master[lchip]->static_fdb_limit = static_limit_en ? 1:0;
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_l2_init_sw(uint8 lchip)
{
    uint32 ds_mac_size = 0;
    ctc_spool_t spool;
    int32    ret = CTC_E_NONE;
    uint8  bind_ldp_en = 0;

    sal_memset(&spool, 0, sizeof(ctc_spool_t));

    pl2_usw_master[lchip]->fdb_hash = ctc_hash_create(FDB_MAC_FID_HASH_SIZE/CTC_HASH_512_BLOCK_SIZE,
                                           CTC_HASH_512_BLOCK_SIZE,
                                           (hash_key_fn) _sys_usw_l2_fdb_hash_make,
                                           (hash_cmp_fn) _sys_usw_l2_fdb_hash_compare);
    if (!pl2_usw_master[lchip]->fdb_hash)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_0;
    }

    /* alloc fdb mac hash size  */

    CTC_ERROR_GOTO(sys_usw_ftm_query_table_entry_num(lchip, DsMac_t, &ds_mac_size), ret, error_0);

    spool.lchip = lchip;
    spool.block_num = CTC_VEC_BLOCK_NUM(ds_mac_size, FDB_MAC_FID_HASH_B);
    spool.block_size = FDB_MAC_FID_HASH_B;
    spool.max_count = ds_mac_size;
    spool.user_data_size = CTC_OFFSET_OF(sys_l2_ad_t, calc_key_len);
    spool.param_offset = CTC_OFFSET_OF(sys_l2_ad_t, param);
    spool.spool_key = (hash_key_fn) _sys_usw_l2_ad_spool_hash_make;
    spool.spool_cmp = (hash_cmp_fn) _sys_usw_l2_ad_spool_hash_cmp;
    spool.spool_alloc = (spool_alloc_fn)_sys_usw_l2_ad_spool_alloc_index;
    spool.spool_free = (spool_free_fn)_sys_usw_l2_ad_spool_free_index;
    pl2_usw_master[lchip]->ad_spool = ctc_spool_create(&spool);
    if (!pl2_usw_master[lchip]->ad_spool)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_0;
    }

    pl2_usw_master[lchip]->fid_vec = ctc_vector_init(CTC_VEC_BLOCK_NUM(pl2_usw_master[lchip]->cfg_max_fid + 1, FDB_DFT_HASH_B),
                                          FDB_DFT_HASH_B);
    if (!pl2_usw_master[lchip]->fid_vec)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error_0;
    }

    if (pl2_usw_master[lchip]->cfg_vport_num)
    {
        pl2_usw_master[lchip]->vport2nh_vec = ctc_vector_init(CTC_VEC_BLOCK_NUM(pl2_usw_master[lchip]->cfg_vport_num, FDB_LOGIC_PORT_VEC_B),
                                                   FDB_LOGIC_PORT_VEC_B);
        if (!pl2_usw_master[lchip]->vport2nh_vec)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }
    }

    SYS_L2_REG_SYN_ADD_DB_CB(lchip, add);
    SYS_L2_REG_SYN_DEL_DB_CB(lchip, remove);
    pl2_usw_master[lchip]->mcast_member_update_pbmp = (DRV_FROM_AT(lchip)) ? _sys_at_l2_update_nh_by_port_bmp :
                                                     _sys_usw_l2_update_nh_by_port_bmp;

    CTC_ERROR_GOTO(sys_usw_nh_get_bind_ldp_en(lchip, &bind_ldp_en), ret, error_0);
    if(DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && bind_ldp_en))
    {
        pl2_usw_master[lchip]->ldp_hash = ctc_hash_create(FDB_MAC_FID_HASH_SIZE/CTC_HASH_512_BLOCK_SIZE, CTC_HASH_512_BLOCK_SIZE,
                                                        (hash_key_fn)sys_usw_ldp_hash_make,
                                                        (hash_cmp_fn)sys_usw_ldp_hash_cmp);
        if (!pl2_usw_master[lchip]->ldp_hash)
        {
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }
        pl2_usw_master[lchip]->ad_hash = ctc_hash_create(CTC_VEC_BLOCK_NUM(ds_mac_size, FDB_MAC_FID_HASH_B), FDB_MAC_FID_HASH_B,
                                                        (hash_key_fn)_sys_usw_l2_ad_hash_make,
                                                        (hash_cmp_fn)_sys_usw_l2_ad_hash_cmp);
        if (!pl2_usw_master[lchip]->ad_hash)
        {
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }
    }

    if(DRV_FROM_TMM(lchip))
    {
        pl2_usw_master[lchip]->nhid_hash = ctc_hash_create((FDB_MAC_NHID_HASH_SIZE + CTC_HASH_1K_BLOCK_SIZE-1)/CTC_HASH_1K_BLOCK_SIZE, CTC_HASH_1K_BLOCK_SIZE,
                                                        (hash_key_fn)sys_usw_ldp_hash_make,
                                                        (hash_cmp_fn)sys_usw_ldp_hash_cmp);
        if (!pl2_usw_master[lchip]->nhid_hash)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto error_0;
        }
    }
    return CTC_E_NONE;
error_0:
    if (pl2_usw_master[lchip]->fid_vec)
    {
        ctc_vector_release(pl2_usw_master[lchip]->fid_vec);
    }
    if (pl2_usw_master[lchip]->ad_spool)
    {
        ctc_spool_free(pl2_usw_master[lchip]->ad_spool);
    }
    if (pl2_usw_master[lchip]->fdb_hash)
    {
        ctc_hash_free(pl2_usw_master[lchip]->fdb_hash);
    }
    if(pl2_usw_master[lchip]->ldp_hash)
    {
        ctc_hash_free(pl2_usw_master[lchip]->ldp_hash);
    }
    if(pl2_usw_master[lchip]->ad_hash)
    {
        ctc_hash_free(pl2_usw_master[lchip]->ad_hash);
    }
    if(pl2_usw_master[lchip]->nhid_hash)
    {
        ctc_hash_free(pl2_usw_master[lchip]->nhid_hash);
    }
    return ret;
}

STATIC int32
_sys_usw_l2_init_default_entry(uint8 lchip, uint16 default_entry_num)
{
    uint32                         cmd          = 0;
    uint32                         start_offset = 0;
    uint32                         fld_value    = 0;
    uint16                         fid          = 0;
    sys_l2_info_t                  sys;
    FibEngineLookupResultCtl_m fib_engine_lookup_result_ctl;
    FibEngineCtl_m fib_engine_ctl;

    /* get the start offset of DaMac */
    CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 0, default_entry_num, 1, &start_offset));

    /*here must be multiple of 256*/
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Start Offset:%d\n", start_offset);
    pl2_usw_master[lchip]->dft_entry_base = start_offset;


    fld_value = ((pl2_usw_master[lchip]->dft_entry_base >> 8) & 0xFF);

    sal_memset(&fib_engine_lookup_result_ctl, 0, sizeof(fib_engine_lookup_result_ctl));
    sal_memset(&fib_engine_ctl, 0, sizeof(fib_engine_ctl));

    cmd = DRV_IOR(FibEngineLookupResultCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_engine_lookup_result_ctl));

    DRV_SET_FIELD_V(lchip, FibEngineLookupResultCtl_t,                                        \
                        FibEngineLookupResultCtl_gMacDaLookupResultCtl_defaultEntryBase_f, \
                        &fib_engine_lookup_result_ctl, fld_value);

    DRV_SET_FIELD_V(lchip, FibEngineLookupResultCtl_t,                                      \
                        FibEngineLookupResultCtl_gMacDaLookupResultCtl_defaultEntryEn_f, \
                        &fib_engine_lookup_result_ctl, TRUE);

    DRV_SET_FIELD_V(lchip, FibEngineLookupResultCtl_t,                                        \
                        FibEngineLookupResultCtl_gMacSaLookupResultCtl_defaultEntryBase_f, \
                        &fib_engine_lookup_result_ctl, fld_value);

    DRV_SET_FIELD_V(lchip, FibEngineLookupResultCtl_t,                                      \
                        FibEngineLookupResultCtl_gMacSaLookupResultCtl_defaultEntryEn_f, \
                        &fib_engine_lookup_result_ctl, TRUE);

    cmd = DRV_IOW(FibEngineLookupResultCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_engine_lookup_result_ctl));

    cmd = DRV_IOW(FibEngineCtl_t, DRV_ENTRY_FLAG);

    DRV_SET_FIELD_V(lchip, FibEngineCtl_t,                                      \
                        FibEngineCtl_ipMcastLkpDefaultEntryMinIndex_f, \
                        &fib_engine_ctl, pl2_usw_master[lchip]->dft_entry_base);
    DRV_SET_FIELD_V(lchip, FibEngineCtl_t,                                      \
                        FibEngineCtl_ipMcastLkpDefaultEntryMaxIndex_f, \
                        &fib_engine_ctl, pl2_usw_master[lchip]->dft_entry_base + default_entry_num - 1);

    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_engine_ctl));

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dft_entry_base = 0x%x \n", pl2_usw_master[lchip]->dft_entry_base);


    sal_memset(&sys, 0, sizeof(sys));
    sys.addr_type = SYS_L2_ADDR_TYPE_DEFAULT;
    sys.revert_default    = 1;

    for (fid = 0; fid < pl2_usw_master[lchip]->cfg_max_fid; fid++)
    {
        sys.ad_index = DEFAULT_ENTRY_INDEX(fid);
        CTC_ERROR_RETURN(_sys_usw_l2_write_hw(lchip, &sys));
    }

    return CTC_E_NONE;
}



STATIC int32
_sys_usw_l2_set_global_cfg(uint8 lchip, ctc_l2_fdb_global_cfg_t* pcfg, uint8 vp_alloc_en)
{
    uint32 cmd = 0;
    uint32 value = 0;

    CTC_PTR_VALID_CHECK(pcfg);

    /* allocate logic_port_2_nh vec, only used for logic_port use hw learning */
    /* set the num of logic port */
    pl2_usw_master[lchip]->cfg_vport_num = pcfg->logic_port_num;
    pl2_usw_master[lchip]->cfg_hw_learn  = pcfg->hw_learn_en ? 1:0;
    pl2_usw_master[lchip]->trie_sort_en  = pcfg->trie_sort_en ? 1:0;
    if (pl2_usw_master[lchip]->trie_sort_en)
    {
        sys_usw_fdb_sort_register_fdb_entry_cb(lchip, sys_usw_l2_get_fdb_entry_cb);
        sys_usw_fdb_sort_register_trie_sort_cb(lchip, sys_usw_l2_fdb_trie_sort_en);
    }
    sys_usw_l2_set_static_mac_limit(lchip, pcfg->static_fdb_limit_en);

    CTC_MAX_VALUE_CHECK(pcfg->default_entry_rsv_num, DRV_FROM_TMM(lchip)?0x7FFF:0x3FFF);
    if (pcfg->default_entry_rsv_num)
    {
        pl2_usw_master[lchip]->cfg_max_fid = pcfg->default_entry_rsv_num - 1;
    }
    else
    {
        pl2_usw_master[lchip]->cfg_max_fid = 5 * 1024 - 1;     /*default num 5K*/
    }

    /* add default entry */
    CTC_ERROR_RETURN(_sys_usw_l2_init_default_entry(lchip, pl2_usw_master[lchip]->cfg_max_fid + 1));

    /* stp init */
    CTC_ERROR_RETURN(sys_usw_stp_init(lchip, pcfg->stp_mode));

    /*default is 0*/
    pl2_usw_master[lchip]->vp_alloc_ad_en = vp_alloc_en;
    if (pl2_usw_master[lchip]->vp_alloc_ad_en && !pl2_usw_master[lchip]->cfg_hw_learn)
    {
        DsMac_m dsmac;
        sal_memset(&dsmac, 0, sizeof(dsmac));

        value = 1;
        cmd = DRV_IOW(FibAccelerationCtl_t, FibAccelerationCtl_logicSrcPortAdType_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dsmac));
        SetDsMac(V, learnSource_f, &dsmac, 1);
        SetDsMac(V, fastLearningEn_f, &dsmac, 1);
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &dsmac));
    }

    /*Configure Max logic port*/
    {
        value = vp_alloc_en?0xffff:pcfg->logic_port_num;
        cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_maxLearningLogicSrcPort_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }

    if (DRV_FROM_TMM(lchip))
    {
        /* used for default entry cid */

        value = 0;
        cmd = DRV_IOW(IpeBridgeCtl_t, IpeBridgeCtl_dsMacDefaultCidBase_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        value = 0;
        cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_dsMacDefaultCidBase_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }

    if (DRV_FROM_AT(lchip))
    {
        value = 1;
        cmd = DRV_IOW(IpeBridgeCtl_t, IpeBridgeCtl_tunnelEcmpNewMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        value = 1;
        cmd = DRV_IOW(IpeBridgeCtl_t, IpeBridgeCtl_gUnknownFwdCfg_0_unknownMcastFwdOffset_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        cmd = DRV_IOW(IpeBridgeCtl_t, IpeBridgeCtl_gUnknownFwdCfg_0_unknownUcastFwdOffset_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        cmd = DRV_IOW(IpeBridgeCtl_t, IpeBridgeCtl_macDaPolicerControlBit_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }


    if(pcfg->flag)
    {
        IpeLearningCtl_m ipe_learn_ctl;
        cmd = DRV_IOR(IpeLearningCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_learn_ctl));
        SetIpeLearningCtl(V, srcMismatchDiscardException_f, &ipe_learn_ctl, \
            CTC_FLAG_ISSET(pcfg->flag, CTC_L2_SRC_MISMATCH_DISCARD_TO_CPU)?1:0);
        SetIpeLearningCtl(V, srcMismatchNoDiscardException_f, &ipe_learn_ctl, \
            CTC_FLAG_ISSET(pcfg->flag, CTC_L2_SRC_MISMATCH_FWD_TO_CPU)?1:0);
        cmd = DRV_IOW(IpeLearningCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ipe_learn_ctl));
        pl2_usw_master[lchip]->station_move_no_learn = CTC_FLAG_ISSET(pcfg->flag, CTC_L2_SRC_MISMATCH_NO_LEARN) ?1:0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_set_register(uint8 lchip, uint8 hw_en)
{
    uint32                 cmd   = 0;
    FibAccelerationCtl_m fib_acceleration_ctl;
 /*-    FibAccDrainEnable_m fib_drain_ctl;*/
    uint32 value = 0;
    uint32 cmd1 = 0;
    uint32 cmd2 = 0;
    uint32 cmd3 = 0;
    uint32 cmd4 = 0;
    uint32 cmd5 = 0;
    uint32 cmd6 = 0;
    uint32 field_value = 0;
    uint8 lgchip = 0;
    uint8 hw_sync_en = 0;
    uint8 learn_cache_en = DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1) ? 1 : 0;
    sal_memset(&fib_acceleration_ctl, 0, sizeof(fib_acceleration_ctl));
   /*-TBD  sal_memset(&fib_drain_ctl, 0, sizeof(FibAccDrainEnable_m));*/

    cmd = DRV_IOR(FibAccelerationCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_acceleration_ctl));

    field_value = pl2_usw_master[lchip]->cfg_hw_learn?1:0;
    SetFibAccelerationCtl(V, fastAgingIgnoreFifoFull_f, &fib_acceleration_ctl, field_value);
    SetFibAccelerationCtl(V, fastLearningIgnoreFifoFull_f, &fib_acceleration_ctl, field_value);

    /* for hw_aging gb alwasy set 1 */
    field_value =learn_cache_en ? 0 : pl2_usw_master[lchip]->cfg_hw_learn;
    cmd = DRV_IOW(IpeAgingCtl_t, IpeAgingCtl_hwAgingEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));


    /* always set hardware aging. like the bit in dsaging. */
    SetFibAccelerationCtl(V, hardwareAgingEn_f, &fib_acceleration_ctl, 1);
    sys_usw_get_gchip_id(lchip, &lgchip);
    SetFibAccelerationCtl(V, learningOnStacking_f, &fib_acceleration_ctl, hw_en);
    SetFibAccelerationCtl(V, chipId_f, &fib_acceleration_ctl, lgchip);
    if (learn_cache_en)
    {
        SetFibAccelerationCtl(V, learningCacheModeWriteCacheCtl_f, &fib_acceleration_ctl, 0xF);
        SetFibAccelerationCtl(V, learningCacheModeToDmaEnable_f, &fib_acceleration_ctl, 0xF);
    }
    cmd = DRV_IOW(FibAccelerationCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_acceleration_ctl));



#if 0
    /* set IpeLearningCtl.macTableFull always 1 to support while-list function */
    cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_macTableFull_f);
    value = 1;
    if(TRUE)
    {
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
    }
#endif


    value = hw_en;
    cmd1 = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_learningOnStacking_f);
    cmd2 = DRV_IOW(EpeHdrAdjustCtl_t, EpeHdrAdjustCtl_learningOnStacking_f);
    cmd3 = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_learningOnStacking_f);
    cmd4 = DRV_IOW(IpeHeaderAdjustCtl_t, IpeHeaderAdjustCtl_learningOnStacking_f);
    cmd5 = DRV_IOW(IpeLookupCtl_t, IpeLookupCtl_learningOnStacking_f);
    cmd6 = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_stackingLearningType_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd1, &value));
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd2, &value));
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd3, &value));
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd4, &value));
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd5, &value));
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd6, &value));

    /*Set acc priority*/
    value = 1;
    cmd = DRV_IOW(FibAccMiscCtl_t, FibAccMiscCtl_forceHighPriorityEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    CTC_ERROR_RETURN(sys_usw_dma_get_hw_learning_sync(lchip, &hw_sync_en));
    CTC_ERROR_RETURN(sys_usw_learning_aging_set_hw_sync(lchip, hw_sync_en));

    if (learn_cache_en)
    {
        sys_com_eunit_learning_aging_cfg_t learning_aging_cfg;
        value = 1;
        cmd = DRV_IOW(MacLearningCacheModeEnCtl_t, MacLearningCacheModeEnCtl_cacheLookupEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        cmd = DRV_IOW(FibAccMiscCtl_t, FibAccMiscCtl_learnCacheEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        sal_memset(&learning_aging_cfg, 0, sizeof(sys_com_eunit_learning_aging_cfg_t));
#if (SDB_MEM_MODEL != SDB_MODE)
        if (CTC_E_NONE == SYS_CB(SYS_CB_EUNIT_GET_CFG, lchip, SYS_COM_EUNIT_CFG_LEARNING_AGING, &learning_aging_cfg))
        {
            learning_aging_cfg.enable = hw_en;
            learning_aging_cfg.enable_valid = 1;
            CTC_ERROR_RETURN(SYS_CB(SYS_CB_EUNIT_SET_CFG, lchip, SYS_COM_EUNIT_CFG_LEARNING_AGING, &learning_aging_cfg));
        }
#endif
    }

    return CTC_E_NONE;
}
STATIC int32
_sys_usw_l2_reserve_port_dsmac(uint8 lchip, uint8 gchip, uint32 ad_base, uint32 max_port_num, uint8 rchip_slice_bmp)
{
    uint32        cmd   = 0;
    DsMac_m      macda;
    uint32        dest_gport = 0;
    sys_l2_info_t sys;
    uint32        nhid = 1;
    uint16       loop = 0;
    uint16        drv_lport = 0;
    sal_memset(&macda, 0, sizeof(DsMac_m));
    sal_memset(&sys, 0, sizeof(sys_l2_info_t));

    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);

    if (!sys_usw_chip_is_local(lchip, gchip))
    {
        CTC_SET_FLAG(sys.addr.l2_addr.flag, CTC_L2_FLAG_REMOTE_DYNAMIC);
    }
    
    for (loop = 0; loop< max_port_num; loop++)
    {
        if(CTC_IS_BIT_SET(rchip_slice_bmp, 0) && CTC_IS_BIT_SET(rchip_slice_bmp, 1))
        {
            drv_lport = (loop >= (max_port_num>>1)) ? (loop + SYS_USW_RCHIP_SLICE_PORT_NUM -(max_port_num>>1)): loop;
        }
        else if(CTC_IS_BIT_SET(rchip_slice_bmp, 1))
        {
            drv_lport = loop + SYS_USW_RCHIP_SLICE_PORT_NUM;
        }
        else
        {
            drv_lport = loop;
        }
        if(sys_usw_chip_is_local(lchip, gchip) && 0 == sys_usw_chip_get_fwd_port_en(lchip, drv_lport))
        {
            continue;
        }
        
        nhid = 0;
        dest_gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, drv_lport);

        /*get nexthop id from gport*/
        sys_usw_l2_get_ucast_nh(lchip, dest_gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC, &nhid);
        if (!nhid)
        {
            continue;
        }
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nhid, &sys.nh_info_dsnh, 0));

        CTC_ERROR_RETURN(_sys_usw_l2_map_nh_to_sys(lchip, nhid, &sys, 0, dest_gport, 0));

        CTC_ERROR_RETURN(_sys_usw_l2_encode_dsmac(lchip, &macda, &sys));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ad_base + loop, cmd, &macda));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_reserve_ad_index(uint8 lchip)
{
    uint32 rsv_ad_num = 0;
    uint32 offset     = 0;
    uint32 cmd = 0;
    uint8 gchip = 0;
    uint16 lport = 0;
    FibAccelerationCtl_m fib_acceleration_ctl;

    rsv_ad_num = SYS_USW_MAX_LINKAGG_GROUP_NUM + SYS_USW_MAX_PORT_NUM_PER_CHIP;

    if (!pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
         /*only hw learning should reserve AD for logic port*/
        rsv_ad_num += pl2_usw_master[lchip]->cfg_vport_num;
    }

    CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, rsv_ad_num, 1, &offset));
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " logic_port_num: 0x%x  rsv_ad_num:0x%x  offset:0x%x\n",
                     pl2_usw_master[lchip]->cfg_vport_num, rsv_ad_num, offset);

    for(lport = 0; lport < SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
    {
        if(sys_usw_chip_get_fwd_port_en(lchip, lport))
        {
            continue;
        }
        sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, offset + SYS_USW_MAX_LINKAGG_GROUP_NUM + lport);
    }

    sal_memset(&fib_acceleration_ctl, 0, sizeof(fib_acceleration_ctl));
    cmd = DRV_IOR(FibAccelerationCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_acceleration_ctl));

    if (pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        if (pl2_usw_master[lchip]->cfg_hw_learn)
        {
            /*base from default entry+drop rsv*/
            SetFibAccelerationCtl(V, dsMacBase0_f, &fib_acceleration_ctl, (pl2_usw_master[lchip]->dft_entry_base+pl2_usw_master[lchip]->cfg_max_fid+2)); /*logic port base*/
            pl2_usw_master[lchip]->dsmac_base[SYS_L2_DSMAC_BASE_VPORT] = (pl2_usw_master[lchip]->dft_entry_base+pl2_usw_master[lchip]->cfg_max_fid+2);
        }
    }
    else
    {
        SetFibAccelerationCtl(V, dsMacBase0_f, &fib_acceleration_ctl, offset + SYS_USW_MAX_LINKAGG_GROUP_NUM + SYS_USW_MAX_PORT_NUM_PER_CHIP); /*logic port*/
        pl2_usw_master[lchip]->dsmac_base[SYS_L2_DSMAC_BASE_VPORT] = offset+ SYS_USW_MAX_LINKAGG_GROUP_NUM + SYS_USW_MAX_PORT_NUM_PER_CHIP;
    }
    SetFibAccelerationCtl(V, dsMacBase1_f, &fib_acceleration_ctl, offset + SYS_USW_MAX_LINKAGG_GROUP_NUM);      /*gport*/
    SetFibAccelerationCtl(V, dsMacBase2_f, &fib_acceleration_ctl, offset);                  /*linkagg*/
    pl2_usw_master[lchip]->dsmac_base[SYS_L2_DSMAC_BASE_TRUNK] = offset;
    pl2_usw_master[lchip]->dsmac_base[SYS_L2_DSMAC_BASE_GPORT] = offset+SYS_USW_MAX_LINKAGG_GROUP_NUM;

    cmd = DRV_IOW(FibAccelerationCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &fib_acceleration_ctl));
     /*sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_VPORT) = offset + SYS_USW_MAX_LINKAGG_GROUP_NUM + SYS_USW_MAX_PORT_NUM_PER_CHIP;*/
     /*sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_GPORT) = offset + SYS_USW_MAX_LINKAGG_GROUP_NUM;*/
     /*sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK) = offset;*/

    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_ERROR_RETURN(_sys_usw_l2_reserve_port_dsmac(lchip, gchip,  offset + SYS_USW_MAX_LINKAGG_GROUP_NUM, SYS_USW_MAX_PORT_NUM_PER_CHIP, 1));


    return CTC_E_NONE;
}

/* for stacking */
int32
sys_usw_l2_get_rchip_rsv_ad(uint8 lchip, uint8 gchip, uint16* p_rsv_num)
{
    SYS_GLOBAL_CHIPID_CHECK(gchip);
    SYS_L2_INIT_CHECK();

    /*if gchip is local, return */
    if (sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_NONE;
    }

    L2_LOCK;
    *p_rsv_num = pl2_usw_master[lchip]->rchip_ad_rsv[gchip] & 0x3FFF;
    L2_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_l2_reserve_rchip_ad_index(uint8 lchip, uint8 gchip, uint16 max_port_num, uint8 rchip_slice_bmp)
{
    uint32 rsv_ad_num = 0;
    uint32 offset     = 0;
    uint32 value = 0;
    int32  ret = 0;
    uint32 cmd = 0;
    FibAccelerationRemoteChipAdBase_m fib_acceleration_ctl;
    uint32 index = DRV_FROM_AT(lchip)? gchip : 0;
    uint32 fld_id = DRV_FROM_AT(lchip)? FibAccelerationRemoteChipAdBase_remoteChipAdBase_f : (FibAccelerationRemoteChipAdBase_array_0_remoteChipAdBase_f + gchip);

    SYS_GLOBAL_CHIPID_CHECK(gchip);
    SYS_L2_INIT_CHECK();


    /*if gchip is local, return */
    if (sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_NONE;
    }

    L2_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);
    rsv_ad_num = max_port_num;
    CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, rsv_ad_num, 64, &offset), ret, error_0);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Alloc  rsv_ad_num:0x%x  offset:0x%x\n", rsv_ad_num, offset);
    /*bit14--slice0, bit15--slice1*/
    value = (offset>>6);
    CTC_ERROR_GOTO(_sys_usw_l2_reserve_port_dsmac(lchip, gchip, offset, max_port_num, rchip_slice_bmp), ret, error_0);
    pl2_usw_master[lchip]->rchip_ad_rsv[gchip] = (rsv_ad_num | ((rchip_slice_bmp & 0x3) << 14));
    cmd = DRV_IOR(FibAccelerationRemoteChipAdBase_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &fib_acceleration_ctl), ret, error_0);
    DRV_IOW_FIELD(lchip, FibAccelerationRemoteChipAdBase_t, fld_id, &value, &fib_acceleration_ctl);
    cmd = DRV_IOW(FibAccelerationRemoteChipAdBase_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &fib_acceleration_ctl), ret, error_0);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "DsMac rsv num for rchip:%d, base:0x%x\n",rsv_ad_num,offset);
 error_0:
    L2_UNLOCK;
    return ret;
}

/* for stacking */
int32
sys_usw_l2_free_rchip_ad_index(uint8 lchip, uint8 gchip, uint16 max_port_num)
{
    uint32 offset     = 0;
    int32  ret = 0;
    uint32 cmd = 0;
    FibAccelerationRemoteChipAdBase_m fib_acceleration_ctl;
    uint32 index = DRV_FROM_AT(lchip)? gchip : 0;
    uint32 fld_id = DRV_FROM_AT(lchip)? FibAccelerationRemoteChipAdBase_remoteChipAdBase_f : (FibAccelerationRemoteChipAdBase_array_0_remoteChipAdBase_f + gchip);

    SYS_GLOBAL_CHIPID_CHECK(gchip);
    SYS_L2_INIT_CHECK();

    /*if gchip is local, return */
    if (sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(FibAccelerationRemoteChipAdBase_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fib_acceleration_ctl));
    DRV_IOR_FIELD(lchip, FibAccelerationRemoteChipAdBase_t, fld_id, &offset, &fib_acceleration_ctl);
    offset = (offset << 6);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Free  rsv_ad_num:0x%x  offset:0x%x\n", max_port_num, offset);

    if (0 == offset)
    {
        return CTC_E_NONE;
    }
    L2_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);
    CTC_ERROR_GOTO(sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, max_port_num, offset), ret, error_0);

    offset = 0;
    pl2_usw_master[lchip]->rchip_ad_rsv[gchip] = 0;
    DRV_IOW_FIELD(lchip, FibAccelerationRemoteChipAdBase_t, fld_id, &offset, &fib_acceleration_ctl);
    cmd = DRV_IOW(FibAccelerationRemoteChipAdBase_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, cmd, &fib_acceleration_ctl), ret, error_0);
 error_0:
    L2_UNLOCK;
    return ret;
}

int32
sys_usw_l2_get_fid_num(uint8 lchip, uint16* p_fid_num)
{
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_fid_num);

    L2_LOCK;

    *p_fid_num = pl2_usw_master[lchip]->cfg_max_fid + 1;

    L2_UNLOCK;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_set_hw_learn(uint8 lchip, uint8 hw_en)
{
    uint32 cmd      = 0;
    uint32 value    = 0;
    uint8 learn_cache_en = DRV_FROM_AT(lchip) && (drv_vchip_get_core_num(lchip) > 1) ? 1 : 0;

    /* a nicer solution. */
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);

    value = (!learn_cache_en && hw_en) ? 1:0;
    cmd = DRV_IOW(IpeLearningCtl_t, IpeLearningCtl_fastLearningEn_f);
    DRV_FIELD_IOCTL(lchip, 0, cmd, &value);

    pl2_usw_master[lchip]->cfg_hw_learn = hw_en;

    if(learn_cache_en)
    {
        drv_usw_set_eunit_lock_en(lchip, hw_en);
    }

    return _sys_usw_l2_set_register(lchip, hw_en);
}
int32
sys_usw_l2_set_hw_learn(uint8 lchip, uint8 hw_en)
{
    SYS_L2_INIT_CHECK();

    if(pl2_usw_master[lchip]->cfg_hw_learn == hw_en)
    {
        return CTC_E_NONE;
    }
    if(pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        return CTC_E_NOT_SUPPORT;
    }

    return _sys_usw_l2_set_hw_learn(lchip, hw_en);
}

int32
sys_usw_l2_mc_ftm_cb(uint8 lchip, sys_ftm_specs_info_t* specs_info)
{
    CTC_PTR_VALID_CHECK(specs_info);
    SYS_L2_INIT_CHECK();

    specs_info->used_size = pl2_usw_master[lchip]->l2mc_count;

    return CTC_E_NONE;
}

int32
sys_usw_l2_fdb_ftm_cb(uint8 lchip, sys_ftm_specs_info_t* specs_info)
{
    uint32 cmd = 0;
    uint32 value = 0;

    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOR(MacLimitSystemCount_t, MacLimitSystemCount_profileRunningCount_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }
    else
    {
        cmd = DRV_IOR(MacLimitSystem_t, MacLimitSystem_profileRunningCount_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }
    specs_info->used_size = value;

    return CTC_E_NONE;
}

/*Update ldp for nexthop ldp tunnel underlay change*/
int32
sys_usw_l2_update_ldp_dsmac(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    ctc_list_pointer_node_t * node;
    sys_l2_ad_update_node_t * p_ad_node;
    uint32 cmdr = 0;
    uint32 cmdw = 0;
    DsMac_m ds_mac;
    sys_l2_vport_2_nhid_t* p_node;
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;
    sys_l2_ad_t temp_new_ad_node;
    sys_l2_ad_t temp_old_ad_node;
    DsMac_m ds_mac_old;
    if ((0 == p_param->is_srv6) &&SYS_NH_OVERLAY_NEW_MODE(lchip))
    {
        return CTC_E_NONE;
    }
    L2_LOCK;

     /*update dynamic FDB, logic port bind nhid*/
     p_node = ctc_vector_get(pl2_usw_master[lchip]->vport2nh_vec, p_param->ldp);
     if (NULL != p_node && p_node->use_ldp)
     {
         cmdr = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
         DRV_IOCTL(lchip, p_node->ad_idx, cmdr, &ds_mac);

         SetDsMac(V, destMap_f, &ds_mac, p_param->destmap);
         SetDsMac(V, tunnelEcmpHighBit_f, &ds_mac, (p_param->ecmp_gid >> 11)&0x1);
         SetDsMac(V, adDestMap_f, &ds_mac, p_param->destmap);

         cmdw = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
         DRV_IOCTL(lchip, p_node->ad_idx, cmdw, &ds_mac);

         SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsMac adIndex:%d, destmap:0x%x, ecmpGid:%d\n",
            p_node->ad_idx, p_param->destmap, p_param->ecmp_gid);
     }

    ldp_node.ldp = p_param->ldp;
    p_ldp_node = ctc_hash_lookup(pl2_usw_master[lchip]->ldp_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        L2_UNLOCK;
        return CTC_E_NONE;
    }
    cmdr = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    cmdw = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);

    sal_memset(&temp_new_ad_node, 0, sizeof(temp_new_ad_node));
    temp_new_ad_node.param.ds_mac = &ds_mac;
    temp_new_ad_node.param.lchip = lchip;
    
    sal_memset(&temp_old_ad_node, 0, sizeof(temp_old_ad_node));
    temp_old_ad_node.param.ds_mac = &ds_mac_old;
    temp_old_ad_node.param.lchip = lchip;
    
    /*update static FDB, ad spool*/
    CTC_LIST_POINTER_LOOP(node, &p_ldp_node->update_list)
    {
        p_ad_node = _ctc_container_of(node, sys_l2_ad_update_node_t, head);
        
        DRV_IOCTL(lchip, p_ad_node->ad_index, cmdr, &ds_mac);
        sal_memcpy(&ds_mac_old, &ds_mac, sizeof(ds_mac));
        
        SetDsMac(V, destMap_f, &ds_mac, p_param->destmap);
        SetDsMac(V, tunnelEcmpHighBit_f, &ds_mac, ((p_param->ecmp_gid>> 11)&0x1));
        SetDsMac(V, adDestMap_f, &ds_mac, p_param->destmap);

        temp_new_ad_node.index = p_ad_node->ad_index;
        temp_new_ad_node.ldp_en = 1;
        /*Need to change the spool node hash location, because of spool node content changed*/
        ctc_spool_change(pl2_usw_master[lchip]->ad_spool, (void*)&temp_old_ad_node, (void*)&temp_new_ad_node);

        /*write hw in the last step,because of ctc spool change need to read old hw info to cmp*/
        DRV_IOCTL(lchip, p_ad_node->ad_index, cmdw, &ds_mac);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsMac adIndex:%d, destmap:0x%x, ecmpGid:%d\n",
            p_ad_node->ad_index, p_param->destmap, p_param->ecmp_gid);
    }

     L2_UNLOCK;

    return 0;
}

/*Update srh for nexthop srh change*/
int32
sys_usw_l2_update_dsmac_by_nhid(uint8 lchip, sys_com_ldp_update_t* p_param)
{
    ctc_list_pointer_node_t * node = NULL;
    ctc_list_pointer_node_t * node_next = NULL;
    sys_com_ldp_node_t ldp_node;
    sys_com_ldp_node_t* p_ldp_node = NULL;
    uint32 cmdr = 0;
    uint32 cmdw = 0;
    sys_l2_ad_t temp_new_ad_node;
    sys_l2_ad_t temp_old_ad_node;
    sys_l2_ad_update_node_t* p_ad_node = NULL;
    DsMac_m ds_mac;
    DsMac_m ds_mac_old;

    L2_LOCK;
    ldp_node.ldp = p_param->nhid;
    p_ldp_node = ctc_hash_lookup(pl2_usw_master[lchip]->nhid_hash, &ldp_node);
    if (NULL == p_ldp_node)
    {
        L2_UNLOCK;
        return CTC_E_NONE;
    }

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update dsmac, nhid %u, new ldp %u\n", p_param->nhid, p_param->ldp);
    cmdr = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    cmdw = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);

    sal_memset(&temp_new_ad_node, 0, sizeof(temp_new_ad_node));
    temp_new_ad_node.param.ds_mac = &ds_mac;
    temp_new_ad_node.param.lchip = lchip;
    
    sal_memset(&temp_old_ad_node, 0, sizeof(temp_old_ad_node));
    temp_old_ad_node.param.ds_mac = &ds_mac_old;
    temp_old_ad_node.param.lchip = lchip;
    /*write table use dsip while spool node use p_ad_node->ad*/
    CTC_LIST_POINTER_LOOP(node, &p_ldp_node->update_list)
    {
        p_ad_node = _ctc_container_of(node, sys_l2_ad_update_node_t, nhid_list_head);
        DRV_IOCTL(lchip, p_ad_node->ad_index, cmdr, &ds_mac);
        sal_memcpy(&ds_mac_old, &ds_mac, sizeof(ds_mac));

        SetDsMac(V, destMap_f, &ds_mac, p_param->destmap);
        SetDsMac(V, tunnelEcmpHighBit_f, &ds_mac, ((p_param->ecmp_gid>> 11)&0x1));
        SetDsMac(V, adDestMap_f, &ds_mac, p_param->destmap);
        SetDsMac(V, apsBridgeEn_f, &ds_mac, p_param->aps_en);
        if (p_param->dsnh_valid)
        {
            SetDsMac(V, nextHopPtr_f, &ds_mac, p_param->dsnh_offset);
            SetDsMac(V, bypassIngressEdit_f, &ds_mac, p_param->bypass_igr_edit);
            SetDsMac(V, nextHopExt_f, &ds_mac, p_param->nexthop_ext);
        }

        if ((p_ad_node->ldp != p_param->ldp) || (p_param->dsnh_valid))
        {
            /*remove from old ldp list  and add to new ldp list*/
            if(p_ad_node->ldp)
            {
                sys_usw_remove_ldp_node(lchip, pl2_usw_master[lchip]->ldp_hash, p_ad_node->ldp, &p_ad_node->head);
            }

            temp_new_ad_node.index = p_ad_node->ad_index;
            temp_new_ad_node.ldp_en = 1;
            /*Need to change the spool node hash location, because of spool node content changed*/
            ctc_spool_change(pl2_usw_master[lchip]->ad_spool, (void*)&temp_old_ad_node, (void*)&temp_new_ad_node);

            if(p_param->ldp)
            {
                sys_usw_add_ldp_node(lchip, pl2_usw_master[lchip]->ldp_hash, p_param->ldp, &p_ad_node->head);
            }
            p_ad_node->ldp = p_param->ldp;
        }

        /*write hw in the last step,because of ctc spool change need to read old hw info to cmp*/
        DRV_IOCTL(lchip, p_ad_node->ad_index, cmdw, &ds_mac);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "update DsMac adIndex:%d, destmap:0x%x, ecmpGid:%d\n",
            p_ad_node->ad_index, p_param->destmap, p_param->ecmp_gid);
    }

    if (p_param->is_del)
    {
        CTC_LIST_POINTER_LOOP_DEL(node, node_next, &p_ldp_node->update_list)
        {
            p_ad_node = _ctc_container_of(node, sys_l2_ad_update_node_t, nhid_list_head);
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "remove l2 dsmac %u from nhid %u\n", p_ad_node->ad_index , p_ad_node->srv6_nhid);
            sys_usw_remove_ldp_node(lchip, pl2_usw_master[lchip]->nhid_hash, p_ad_node->srv6_nhid, &p_ad_node->nhid_list_head);
            p_ad_node->srv6_nhid = 0;
        }
    }

    L2_UNLOCK;

    return 0;
}

int32
_sys_usw_l2_fdb_init(uint8 lchip, void* l2_fdb_global_cfg, uint8 vp_alloc_en)
{
    uint32 hash_entry_num = 0;
    int32  ret            = 0;
    uint32 spec_fdb = 0;
    uint32 cmd = 0;
    sys_l2_ad_t l2_ad;
    DsMac_m dsmac;

    LCHIP_CHECK(lchip);

    if (pl2_usw_master[lchip]) /*already init */
    {
        return CTC_E_NONE;
    }

    SYS_VCHIP_MASTER_INIT(lchip, pl2_usw_master, CTC_FEATURE_L2);
    CTC_MAX_VALUE_CHECK(((ctc_l2_fdb_global_cfg_t*)l2_fdb_global_cfg)->logic_port_num, MCHIP_CAP(SYS_CAP_MAX_LOGIC_PORT)+1);


    /* get num of Hash Key */
    sys_usw_ftm_query_table_entry_num(lchip, DsFibHost0MacHashKey_t, &hash_entry_num);

    if (0 == hash_entry_num)
    {
        return CTC_E_NO_RESOURCE;
    }

    MALLOC_ZERO(MEM_FDB_MODULE, pl2_usw_master[lchip], sizeof(sys_l2_master_t));
    if (!pl2_usw_master[lchip])
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    ret = sal_mutex_create(&(pl2_usw_master[lchip]->l2_mutex));
    if (ret || !(pl2_usw_master[lchip]->l2_mutex))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    ret = sal_mutex_create(&(pl2_usw_master[lchip]->l2_dump_mutex));
    if (ret || !(pl2_usw_master[lchip]->l2_dump_mutex))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }


    CTC_ERROR_RETURN(_sys_usw_l2_set_global_cfg(lchip, l2_fdb_global_cfg, vp_alloc_en));

    CTC_ERROR_RETURN(sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 0, 1, 1, &(pl2_usw_master[lchip]->ad_index_drop)));

    CTC_ERROR_RETURN(_sys_usw_l2_reserve_ad_index(lchip));

    CTC_ERROR_RETURN(_sys_usw_l2_init_sw(lchip));
    CTC_ERROR_RETURN(_sys_usw_l2_set_hw_learn(lchip, pl2_usw_master[lchip]->cfg_hw_learn));

    CTC_ERROR_RETURN(sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_L2MC,
                                                sys_usw_l2_mc_ftm_cb));

    CTC_ERROR_RETURN(sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_MAC,
                                                sys_usw_l2_fdb_ftm_cb));

    spec_fdb = sys_usw_ftm_get_spec(lchip, CTC_FTM_SPEC_MAC);
    cmd = DRV_FROM_TMM(lchip) ? DRV_IOW(MacLimitMaxCountConfig_t, MacLimitMaxCountConfig_profileMaxCount_f)
                              : DRV_IOW(MacLimitSystem_t, MacLimitSystem_profileMaxCount_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &spec_fdb));

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_RETURN(sys_usw_l2_fdb_wb_restore(lchip));
    }
    else
    {
        /* add static spool for drop ad*/
        sal_memset(&l2_ad, 0, sizeof(l2_ad));
        sal_memset(&dsmac, 0, sizeof(DsMac_m));
        SetDsMac(V, dsFwdPtr_f, &dsmac, SYS_FDB_DISCARD_FWD_PTR);
        SetDsMac(V, protocolExceptionEn_f, &dsmac, 1);
        SetDsMac(V, isStatic_f, &dsmac, 1);
        SetDsMac(V, stormCtlEn_f, &dsmac, 1);
        SetDsMac(V, fastLearningEn_f, &dsmac, 1);
        l2_ad.index = pl2_usw_master[lchip]->ad_index_drop;
        l2_ad.param.ds_mac = &dsmac;
        l2_ad.param.lchip = lchip;
        CTC_ERROR_RETURN(ctc_spool_static_add(pl2_usw_master[lchip]->ad_spool, &l2_ad));
    }

    if (CTC_WB_ENABLE(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_l2_wb_init(lchip));
    }

    hash_entry_num = 1;
    cmd = DRV_IOW(FibAccelerationCtl_t, FibAccelerationCtl_logicPortIgnoreMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &hash_entry_num));
    /* set chip_capability */

    MCHIP_CAP(SYS_CAP_SPEC_LOGIC_PORT_NUM) = pl2_usw_master[lchip]->cfg_vport_num;
    MCHIP_CAP(SYS_CAP_SPEC_MAX_FID)        = pl2_usw_master[lchip]->cfg_max_fid;
    if (DRV_FROM_AT(lchip))
    {
        sys_usw_flow_stats_alloc_fid_type(lchip);
    }
    sys_usw_nh_vxlan_vni_init(lchip);
    CTC_ERROR_RETURN(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MAX,sys_usw_l2_fdb_wb_sync));
    drv_ser_register_hw_reset_cb(lchip, DRV_SER_HW_RESET_CB_TYPE_FDB, sys_usw_fdb_reset_hw);
    CTC_ERROR_RETURN(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_L2, sys_usw_l2_dump_db));
    /*CTC_ERROR_RETURN(sys_usw_ftm_register_change_mem_cb(lchip, sys_usw_l2_fdb_change_mem_cb));*/
    SYS_CB_REGISTER(lchip, SYS_CB_LDP_UPDATE_L2, sys_usw_l2_update_ldp_dsmac);
    SYS_CB_REGISTER(lchip, SYS_CB_NHID_UPDATE_L2, sys_usw_l2_update_dsmac_by_nhid);

    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_L2);
    return CTC_E_NONE;
}



int32
sys_usw_l2_fdb_init(uint8 lchip, void* l2_fdb_global_cfg)
{
    return _sys_usw_l2_fdb_init(lchip, l2_fdb_global_cfg, 0);
}

int32
sys_usw_l2_fdb_init_for_vp_alloc(uint8 lchip, void* l2_fdb_global_cfg, uint8 vp_alloc_en)
{
    for (lchip = SYS_PP_BASE(lchip); lchip < (SYS_PP_BASE(lchip) + SYS_PP_NUM(lchip)); lchip++)
    {
        _sys_usw_l2_fdb_init(lchip, l2_fdb_global_cfg, vp_alloc_en);
    }
    return CTC_E_NONE;
}

#define __DEINIT__
STATIC int32
_sys_usw_l2_fdb_free_node_data(void* node_data, void* user_data)
{
    if (node_data)
    {
        mem_free(node_data);
    }

    return 1;
}

STATIC int32
_sys_usw_l2_free_node_data(void* node_data, void* user_data)
{
    if (node_data)
    {
        mem_free(node_data);
    }

    return CTC_E_NONE;
}

int32
sys_usw_l2_fdb_deinit(uint8 lchip)
{
    uint32 rsv_ad_num = 0;
    LCHIP_CHECK(lchip);
    if (NULL == pl2_usw_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT(lchip, pl2_usw_master, CTC_FEATURE_L2);

    L2_DUMP_LOCK;

    sys_usw_ftm_free_table_offset(lchip, DsMac_t, 0, 1, pl2_usw_master[lchip]->ad_index_drop);
    rsv_ad_num = SYS_USW_MAX_LINKAGG_GROUP_NUM + SYS_USW_MAX_PORT_NUM_PER_CHIP;
    if (!pl2_usw_master[lchip]->vp_alloc_ad_en)
    {
        rsv_ad_num += pl2_usw_master[lchip]->cfg_vport_num;
    }
    sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, rsv_ad_num, sys_usw_l2_get_dsmac_base(lchip, SYS_L2_DSMAC_BASE_TRUNK));
    sys_usw_ftm_free_table_offset(lchip, DsMac_t, 0, pl2_usw_master[lchip]->cfg_max_fid+1, pl2_usw_master[lchip]->dft_entry_base);

    /*free ad data*/
    ctc_spool_free(pl2_usw_master[lchip]->ad_spool);

    /*free fdb hash data*/
    ctc_hash_free2(pl2_usw_master[lchip]->fdb_hash, (hash_traversal_fn)_sys_usw_l2_fdb_free_node_data, NULL);

    if (pl2_usw_master[lchip]->cfg_vport_num)
    {
        /*free vport data*/
        ctc_vector_traverse(pl2_usw_master[lchip]->vport2nh_vec, (vector_traversal_fn)_sys_usw_l2_free_node_data, NULL);
        ctc_vector_release(pl2_usw_master[lchip]->vport2nh_vec);
    }
    /*free fid data*/
    ctc_vector_traverse(pl2_usw_master[lchip]->fid_vec, (vector_traversal_fn)_sys_usw_l2_free_node_data, NULL);
    ctc_vector_release(pl2_usw_master[lchip]->fid_vec);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_L2, NULL);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_L2,0, NULL);
    drv_ser_register_hw_reset_cb(lchip, DRV_SER_HW_RESET_CB_TYPE_FDB, NULL);
    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_L2MC,NULL);
    sys_usw_ftm_register_callback(lchip, CTC_FTM_SPEC_MAC,NULL);
    /*stp deinit*/
    sys_usw_stp_deinit(lchip);
    if(pl2_usw_master[lchip]->ldp_hash)
    {
        ctc_hash_free2(pl2_usw_master[lchip]->ldp_hash, (hash_traversal_fn)sys_usw_free_ldp_node, NULL);
    }
    if(pl2_usw_master[lchip]->ad_hash)
    {
        ctc_hash_free2(pl2_usw_master[lchip]->ad_hash, (hash_traversal_fn)sys_usw_free_ldp_node, NULL);
    }
    if(pl2_usw_master[lchip]->nhid_hash)
    {
        ctc_hash_free2(pl2_usw_master[lchip]->nhid_hash, (hash_traversal_fn)sys_usw_free_ldp_node, NULL);
    }
    L2_DUMP_UNLOCK;
    sal_mutex_destroy(pl2_usw_master[lchip]->l2_dump_mutex);
    sal_mutex_destroy(pl2_usw_master[lchip]->l2_mutex);
    mem_free(pl2_usw_master[lchip]);

    return CTC_E_NONE;
}

int32
sys_usw_l2_fid_bind_policer_id(uint8 lchip, uint16 fid, uint16 policer_id)
{
    uint8  utype = 0;
    uint8  policer_valid = 0;
    uint8  step = DsVsi_array_1_bcastDiscard_f - DsVsi_array_0_bcastDiscard_f;
    uint16 policer_ptr = 0;
    uint32 cmd = 0;
    uint32 index = 0;
    int32 ret = 0;
    sys_qos_policer_t* p_sys_policer = NULL;
    DsVsi_m ds_vsi;
    SYS_L2_INIT_CHECK();
    SYS_L2_FID_CHECK(fid);
    sal_memset(&ds_vsi, 0, sizeof(DsVsi_m));

    L2_LOCK;
    if (policer_id)
    {
        CTC_ERROR_GOTO(sys_usw_qos_lookup_policer(lchip, &p_sys_policer, SYS_QOS_POLICER_TYPE_SVC, CTC_INGRESS, policer_id), ret, error0);
        utype = 1;
        policer_valid = 1;
        policer_ptr = p_sys_policer->policer_ptr & 0xfffc;
    }

    cmd = DRV_IOR(DsVsi_t, DRV_ENTRY_FLAG);
    index = (fid >> 2);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &ds_vsi), ret, error0);
    if (!GetDsVsi(V, array_0_uType_f + (fid & 0x3) * step, &ds_vsi)
        && GetDsVsi(V, array_0_categoryIdValid_f + (fid & 0x3) * step, &ds_vsi))
    {
        ret = CTC_E_PARAM_CONFLICT;
        goto error0;
    }

    SetDsVsi(V, array_0_u_g1_policerPtrValid_f + (fid & 0x3) * step, &ds_vsi, policer_valid);
    SetDsVsi(V, array_0_u_g1_policerPtr_f + (fid & 0x3) * step, &ds_vsi, policer_ptr);
    SetDsVsi(V, array_0_uType_f + (fid & 0x3) * step, &ds_vsi, utype);
    cmd = DRV_IOW(DsVsi_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &ds_vsi), ret, error0);

error0:
    L2_UNLOCK;
    return ret;
}

int32
sys_usw_l2_fid_get_bind_policer(uint8 lchip, uint16 fid, uint8* policer_valid, uint32 *policer_ptr)
{
    uint8  step = DsVsi_array_1_bcastDiscard_f - DsVsi_array_0_bcastDiscard_f;
    uint32 cmd = 0;
    uint32 index = 0;
    int32 ret = 0;
    DsVsi_m ds_vsi;
    SYS_L2_INIT_CHECK();
    SYS_L2_FID_CHECK(fid);
    sal_memset(&ds_vsi, 0, sizeof(DsVsi_m));

    L2_LOCK;
    cmd = DRV_IOR(DsVsi_t, DRV_ENTRY_FLAG);
    index = (fid >> 2);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &ds_vsi), ret, error0);
    if (!GetDsVsi(V, array_0_uType_f + (fid & 0x3) * step, &ds_vsi)
        && GetDsVsi(V, array_0_categoryIdValid_f + (fid & 0x3) * step, &ds_vsi))
    {
        ret = CTC_E_PARAM_CONFLICT;
        goto error0;
    }

    *policer_valid = GetDsVsi(V, array_0_u_g1_policerPtrValid_f + (fid & 0x3) * step, &ds_vsi);
    *policer_ptr = GetDsVsi(V, array_0_u_g1_policerPtr_f + (fid & 0x3) * step, &ds_vsi);

error0:
    L2_UNLOCK;
    return ret;
}
/*type, 0 means bind mcast group; 1 means bind ucast group*/
STATIC INLINE int32
_sys_usw_l2_fdb_bind_mcast_group(uint8 lchip, uint16 fid_id, uint32 value, uint8 bind_type)
{
    uint32 cmd        = 0;
    uint32 index      = 0;
    DsMac_m ds_mac;
    uint32 mcast_nhid;
    sys_nh_info_dsnh_t nh_info = {0};
    sys_l2_fid_node_t* p_fid_node = NULL;
    sys_nh_param_mcast_group_t nh_mc;
    uint8 mcast_en;
    uint8 ucast_en;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    index = DEFAULT_ENTRY_INDEX(fid_id);
    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_mac));

    mcast_en = (DRV_FROM_TMM(lchip)) ? GetDsMacDefault(V, unknownMcastFwdEn_f, &ds_mac): GetDsMac(V, unknownMcastFwdEn_f, &ds_mac);
    ucast_en = (DRV_FROM_TMM(lchip)) ? GetDsMacDefault(V, unknownUcastFwdEn_f, &ds_mac): GetDsMac(V, unknownUcastFwdEn_f, &ds_mac);
    if((mcast_en && bind_type == 1) || (ucast_en && bind_type == 0))
    {
        return CTC_E_PARAM_CONFLICT;
    }
    if(value)
    {
        p_fid_node = _sys_usw_l2_fid_node_lkup(lchip, fid_id);
        if (NULL == p_fid_node)
        {
            return CTC_E_NOT_EXIST;
        }

        CTC_ERROR_RETURN(sys_usw_nh_get_mcast_nh(lchip, p_fid_node->mc_gid, &mcast_nhid));

        sal_memset(&nh_mc, 0, sizeof(nh_mc));
        nh_mc.nhid = mcast_nhid;
        nh_mc.opcode = SYS_NH_PARAM_MCAST_ADD_MEMBER;
        nh_mc.mem_info.member_type = SYS_NH_PARAM_BRGMC_MEM_LOCAL;
        nh_mc.mem_info.destid = SYS_ENCODE_MCAST_IPE_DESTMAP(value);
        CTC_ERROR_RETURN(sys_usw_mcast_nh_update(lchip, &nh_mc));
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, mcast_nhid, &nh_info, 0));

        if(DRV_FROM_TMM(lchip))
        {
            SetDsMacDefault(V, u1Type_f, &ds_mac, 0);
            SetDsMacDefault(V, u_g1_dsFwd_nextHopPtr_f, &ds_mac, 0);
            SetDsMacDefault(V, u_g1_dsFwd_destMap_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownUcastFwdEn_f, &ds_mac, bind_type ? 1:0);
            SetDsMacDefault(V, unknownUcastNextHopEn_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownMcastFwdEn_f, &ds_mac, bind_type ? 0:1);
            SetDsMacDefault(V, unknownMcastNextHopEn_f, &ds_mac, 0);
            SetDsMacDefault(V, u_g0_dsFwdPtr_f, &ds_mac, nh_info.dsfwd_offset);
            SetDsMacDefault(V, unknownFwdAdjustProfile_f, &ds_mac, 0);/* AT */
        }
        else
        {
            SetDsMac(V, nextHopPtrValid_f, &ds_mac, 0);
            SetDsMac(V, adDestMap_f, &ds_mac, 0);
            SetDsMac(V, unknownUcastFwdEn_f, &ds_mac, bind_type ? 1:0);
            SetDsMac(V, unknownUcastNextHopEn_f, &ds_mac, 0);
            SetDsMac(V, unknownMcastFwdEn_f, &ds_mac, bind_type ? 0:1);
            SetDsMac(V, unknownMcastNextHopEn_f, &ds_mac, 0);
            SetDsMac(V, dsFwdPtr_f, &ds_mac, nh_info.dsfwd_offset);
        }

    }
    else
    {
        if(GetDsMac(V, nextHopPtrValid_f, &ds_mac))
        {
            return CTC_E_NOT_EXIST;
        }
        if(DRV_FROM_TMM(lchip))
        {
            SetDsMacDefault(V, unknownUcastFwdEn_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownUcastNextHopEn_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownMcastFwdEn_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownMcastNextHopEn_f, &ds_mac, 0);
            SetDsMacDefault(V, unknownFwdAdjustProfile_f, &ds_mac, 0);/* AT */
        }
        else
        {
            SetDsMac(V, unknownUcastFwdEn_f, &ds_mac, 0);
            SetDsMac(V, unknownUcastNextHopEn_f, &ds_mac, 0);
            SetDsMac(V, unknownMcastFwdEn_f, &ds_mac, 0);
            SetDsMac(V, unknownMcastNextHopEn_f, &ds_mac, 0);
        }
    }
    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_mac));
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_l2_set_fid_property(uint8 lchip, uint16 fid_id, uint32 fid_prop, uint32 value)
{
    uint32 field_id_0 = 0;
    uint32 field_id   = 0;
    uint32 cmd        = 0;
    uint32 index      = 0;
    uint32 tableid    = DsVsi_t;
    uint8  step       = DsVsi_array_1_bcastDiscard_f - DsVsi_array_0_bcastDiscard_f;
    uint8 value1 = 0;
    DsVsi_m ds_vsi;
    ctc_maclimit_action_t action;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    switch (fid_prop)
    {
    case CTC_L2_FID_PROP_LEARNING:
        field_id_0 = DsVsi_array_0_vsiLearningDisable_f;
        value      = (value) ? 0 : 1;
        break;

    case CTC_L2_FID_PROP_IGMP_SNOOPING:
        field_id_0 = DsVsi_array_0_igmpSnoopEn_f;
        value      = (value) ? 1 : 0;
        break;

    case CTC_L2_FID_PROP_DROP_UNKNOWN_MCAST:
        field_id_0 = DsVsi_array_0_mcastDiscard_f;
        value      = (value) ? 1 : 0;
        break;

    case CTC_L2_FID_PROP_DROP_UNKNOWN_UCAST:
        field_id_0 = DsVsi_array_0_ucastDiscard_f;
        value      = (value) ? 1 : 0;
        break;
    case CTC_L2_FID_PROP_DROP_BCAST:
        field_id_0 = DsVsi_array_0_bcastDiscard_f;
        value      = (value) ? 1 : 0;
        break;
    case CTC_L2_FID_PROP_ARP_EXCP_TYPE:
        if (value == 0xff)
        {
            value1 = value;
            value = 0;
        }
        else
        {
            CTC_MAX_VALUE_CHECK(value, MAX_CTC_EXCP_TYPE - 1);
        }
        field_id_0 = DsVsi_array_0_arpExceptionType_f;
        break;
    case CTC_L2_FID_PROP_UNKNOWN_MCAST_COPY_TO_CPU:
        value      = (value) ? 1 : 0;
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOW(DsMacDefault_t, DsMacDefault_unknownMcastException_f) : DRV_IOW(DsMac_t, DsMac_unknownMcastException_f);
        break;

    case CTC_L2_FID_PROP_UNKNOWN_UCAST_COPY_TO_CPU:
        value      = (value) ? 1 : 0;
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOW(DsMacDefault_t, DsMacDefault_unknownUcastException_f) : DRV_IOW(DsMac_t, DsMac_unknownUcastException_f);
        break;

    case CTC_L2_FID_PROP_BCAST_COPY_TO_CPU:
        value      = (value) ? 1 : 0;
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOW(DsMacDefault_t, DsMacDefault_bcastException_f) : DRV_IOW(DsMac_t, DsMac_bcastException_f);
        break;

    case CTC_L2_FID_PROP_IGS_STATS_EN:
        if (DRV_FROM_AT(lchip))
        {
            sys_stats_param_t sts_param;
            sal_memset(&sts_param, 0, sizeof(sts_param));
            sts_param.type = SYS_STATS_TYPE_FID;
            sts_param.ptr = fid_id;
            
            cmd = DRV_IOR(DsVsi_t, DRV_ENTRY_FLAG);
            index = (fid_id >> 2);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_vsi));
            if (value)
            {
                sts_param.id = value;
                CTC_ERROR_RETURN(sys_usw_flow_stats_alloc_statsptr(lchip, &sts_param));
                SetDsVsi(V, array_0_uType_f + (fid_id & 0x3) * step, &ds_vsi, 1);
                cmd = DRV_IOW(DsVsi_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_vsi));
            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_flow_stats_free_statsptr(lchip, &sts_param));
            }
            return CTC_E_NONE;
        }
        else
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
            return CTC_E_NOT_SUPPORT;
        }
        break;
    case CTC_L2_FID_PROP_EGS_STATS_EN:
        if (DRV_FROM_AT(lchip))
        {
            sys_stats_param_t sts_param;
            sal_memset(&sts_param, 0, sizeof(sts_param));
            sts_param.type = SYS_STATS_TYPE_FID;
            sts_param.ptr = fid_id;
            sts_param.dir = CTC_EGRESS;
            if (value)
            {
                sts_param.id = value;
                CTC_ERROR_RETURN(sys_usw_flow_stats_alloc_statsptr(lchip, &sts_param));
            }
            else
            {
                CTC_ERROR_RETURN(sys_usw_flow_stats_free_statsptr(lchip, &sts_param));
            }
            return CTC_E_NONE;
        }
        else
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
            return CTC_E_NOT_SUPPORT;
        }
    case CTC_L2_FID_PROP_BDING_MCAST_GROUP:
         if(DRV_IS_DUET2(lchip))
        {
            return CTC_E_INVALID_PARAM;
        }
        return _sys_usw_l2_fdb_bind_mcast_group(lchip, fid_id, value, 0);
        break;
    case CTC_L2_FID_PROP_BDING_UCAST_GROUP:
         if(DRV_IS_DUET2(lchip))
        {
            return CTC_E_INVALID_PARAM;
        }
        return _sys_usw_l2_fdb_bind_mcast_group(lchip, fid_id, value, 1);
        break;
    case CTC_L2_FID_PROP_CID:
        if(!DRV_FROM_TMM(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }
        SYS_USW_CID_CHECK(lchip, value);

        cmd = DRV_IOR(DsVsi_t, DRV_ENTRY_FLAG);
        index = (fid_id >> 2);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_vsi));
        if (GetDsVsi(V, array_0_uType_f + (fid_id & 0x3) * step, &ds_vsi)
            && GetDsVsi(V, array_0_u_g1_policerPtrValid_f + (fid_id & 0x3) * step, &ds_vsi))
        {
            return CTC_E_PARAM_CONFLICT;
        }
        SetDsVsi(V, array_0_categoryIdValid_f + (fid_id & 0x3) * step, &ds_vsi, value ? 1 : 0);
        SetDsVsi(V, array_0_categoryId_f + (fid_id & 0x3) * step, &ds_vsi, value);
        SetDsVsi(V, array_0_uType_f + (fid_id & 0x3) * step, &ds_vsi, 0);
        cmd = DRV_IOW(DsVsi_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_vsi));
        return CTC_E_NONE;
    case CTC_L2_FID_PROP_MAC_LIMIT_ACTION:
        action = value;
        CTC_ERROR_RETURN(sys_usw_mac_security_set_fid_learn_limit_action(lchip, fid_id, action));
        return CTC_E_NONE;
        break;
    default:
        return CTC_E_INVALID_PARAM;
    }

    if(cmd)
    {
        index = DEFAULT_ENTRY_INDEX(fid_id);
    }
    else
    {
        field_id = field_id_0 + (fid_id & 0x3) * step;
        cmd      = DRV_IOW(tableid, field_id);
        index    = (fid_id >> 2);
    }
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));

    if (fid_prop == CTC_L2_FID_PROP_ARP_EXCP_TYPE)
    {
        value = (value1 == 0xff? 0 : 1);
        field_id = DsVsi_array_0_arpCtlEn_f + (fid_id & 0x3) * step;
        cmd      = DRV_IOW(tableid, field_id);
        index    = (fid_id >> 2);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
    }

    return CTC_E_NONE;

}
int32
sys_usw_l2_set_fid_property(uint8 lchip, uint16 fid_id, uint32 fid_prop, uint32 value)
{
    int32 ret = 0;
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    SYS_L2_FID_CHECK(fid_id);
    L2_LOCK;
    CTC_ERROR_GOTO(_sys_usw_l2_set_fid_property(lchip, fid_id, fid_prop, value), ret, error0);

error0:
    L2_UNLOCK;
    return ret;
}
int32
sys_usw_l2_get_fid_property(uint8 lchip, uint16 fid_id, uint32 fid_prop, uint32* value)
{
    uint32 field_id_0 = 0;
    uint32 field_id   = 0;
    uint32 cmd        = 0;
    uint32 index      = 0;
    uint8  step       = DsVsi_array_1_bcastDiscard_f - DsVsi_array_0_bcastDiscard_f;
    ds_t   ds_mac;
    DsVsi_m ds_vsi;
    DsFwd_m dsfwd;
    DsFwdHalf_m dsfwdhalf;
    uint8 merge_dsfwd;
    uint8 unknown_mcast_en, unknown_ucast_en;
    uint32 dsfwd_ptr;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_L2_INIT_CHECK();
    SYS_L2_FID_CHECK(fid_id);
    CTC_PTR_VALID_CHECK(value);

    switch (fid_prop)
    {
    case CTC_L2_FID_PROP_LEARNING:
        field_id_0 = DsVsi_array_0_vsiLearningDisable_f;
        break;

    case CTC_L2_FID_PROP_IGMP_SNOOPING:
        field_id_0 = DsVsi_array_0_igmpSnoopEn_f;
        break;

    case CTC_L2_FID_PROP_DROP_UNKNOWN_MCAST:
        field_id_0 = DsVsi_array_0_mcastDiscard_f;
        break;

    case CTC_L2_FID_PROP_DROP_UNKNOWN_UCAST:
        field_id_0 = DsVsi_array_0_ucastDiscard_f;
        break;
    case CTC_L2_FID_PROP_DROP_BCAST:
        field_id_0 = DsVsi_array_0_bcastDiscard_f;
        break;
    case CTC_L2_FID_PROP_ARP_EXCP_TYPE:
        field_id_0 = DsVsi_array_0_arpExceptionType_f;
        break;
    case CTC_L2_FID_PROP_UNKNOWN_MCAST_COPY_TO_CPU:
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOR(DsMacDefault_t, DsMacDefault_unknownMcastException_f) : DRV_IOR(DsMac_t, DsMac_unknownMcastException_f);
        break;

    case CTC_L2_FID_PROP_UNKNOWN_UCAST_COPY_TO_CPU:
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOR(DsMacDefault_t, DsMacDefault_unknownUcastException_f) : DRV_IOR(DsMac_t, DsMac_unknownUcastException_f);
        break;

    case CTC_L2_FID_PROP_BCAST_COPY_TO_CPU:
        cmd = DRV_FROM_TMM(lchip) ? DRV_IOR(DsMacDefault_t, DsMacDefault_bcastException_f) : DRV_IOR(DsMac_t, DsMac_bcastException_f);
        break;
    case CTC_L2_FID_PROP_CID:
        if (!DRV_FROM_TMM(lchip))
        {
            return CTC_E_NOT_SUPPORT;
        }

        index    = (fid_id >> 2) & 0xFFF;
        cmd = DRV_IOR(DsVsi_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_vsi));
        if (GetDsVsi(V, array_0_uType_f + (fid_id & 0x3) * step, &ds_vsi)
            || (!DRV_FROM_AT(lchip)&&!GetDsVsi(V, array_0_categoryIdValid_f + (fid_id & 0x3) * step, &ds_vsi))
            ||(DRV_FROM_AT(lchip)&&!GetDsVsi(V, array_0_categoryId_f + (fid_id & 0x3) * step, &ds_vsi)))
        {
            return CTC_E_NOT_EXIST;
        }
        *value = GetDsVsi(V, array_0_categoryId_f + (fid_id & 0x3) * step, &ds_vsi);
        return CTC_E_NONE;
    case CTC_L2_FID_PROP_BDING_MCAST_GROUP:
    case CTC_L2_FID_PROP_BDING_UCAST_GROUP:
        index = DEFAULT_ENTRY_INDEX(fid_id);
        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds_mac));
        if(DRV_FROM_TMM(lchip))
        {
            merge_dsfwd = GetDsMacDefault(V, u1Type_f, &ds_mac);
            unknown_mcast_en = GetDsMacDefault(V, unknownMcastFwdEn_f, &ds_mac);
            unknown_ucast_en = GetDsMacDefault(V, unknownUcastFwdEn_f, &ds_mac);
            dsfwd_ptr = GetDsMacDefault(V, u_g0_dsFwdPtr_f, &ds_mac);
        }
        else
        {
            merge_dsfwd = GetDsMac(V, nextHopPtrValid_f, &ds_mac);
            unknown_mcast_en = GetDsMac(V, unknownMcastFwdEn_f, &ds_mac);
            unknown_ucast_en = GetDsMacDefault(V, unknownUcastFwdEn_f, &ds_mac);
            dsfwd_ptr = GetDsMac(V, dsFwdPtr_f, &ds_mac);
        }
        if(merge_dsfwd || \
            ((CTC_L2_FID_PROP_BDING_MCAST_GROUP == fid_prop) && !unknown_mcast_en) || \
            ((CTC_L2_FID_PROP_BDING_UCAST_GROUP == fid_prop) && !unknown_ucast_en))
        {
            *value = 0;
        }
        else
        {
            cmd = DRV_IOR(DsFwd_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip,  dsfwd_ptr>>1, cmd, &dsfwd));
            GetDsFwdDualHalf(A, g_1_dsFwdHalf_f, &dsfwd,   &dsfwdhalf);
            *value = GetDsFwdHalf(V, destMap_f, &dsfwdhalf) & 0xFFFF;
        }
        return CTC_E_NONE;
        break;
    case CTC_L2_FID_PROP_MAC_LIMIT_ACTION:
        CTC_ERROR_RETURN(sys_usw_mac_security_get_fid_learn_limit_action(lchip, fid_id, value));
        return CTC_E_NONE;
    case CTC_L2_FID_PROP_IGS_STATS_EN:
        CTC_ERROR_RETURN(sys_usw_flow_stats_lookup_statsid(lchip, CTC_STATS_STATSID_TYPE_FID, fid_id, value, CTC_INGRESS));
        return CTC_E_NONE;
    case CTC_L2_FID_PROP_EGS_STATS_EN:
        CTC_ERROR_RETURN(sys_usw_flow_stats_lookup_statsid(lchip, CTC_STATS_STATSID_TYPE_FID, fid_id, value, CTC_EGRESS));
        return CTC_E_NONE;

    default:
        return CTC_E_INVALID_PARAM;
    }

    if(cmd)
    {
        index = DEFAULT_ENTRY_INDEX(fid_id);
    }
    else
    {
        field_id = field_id_0 + (fid_id & 0x3) * step;
        cmd      = DRV_IOR(DsVsi_t, field_id);
        index    = (fid_id >> 2) & 0xFFF;
    }

    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, value));
    if (CTC_L2_FID_PROP_LEARNING == fid_prop)
    {
        *value = !(*value);
    }
    if (CTC_L2_FID_PROP_ARP_EXCP_TYPE == fid_prop)
    {
        uint32 valie1 = 0;
        field_id_0 = DsVsi_array_0_arpCtlEn_f;
        field_id = field_id_0 + (fid_id & 0x3) * step;
        cmd      = DRV_IOR(DsVsi_t, field_id);
        index    = (fid_id >> 2) & 0xFFF;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &valie1));
        *value = (valie1? *value : 0xff);
    }    

    return CTC_E_NONE;
}


int32
sys_usw_l2_set_default_entry_features(uint8 lchip, ctc_l2dflt_addr_t* l2dflt_addr)
{
    sys_l2_fid_node_t* fid   = NULL;
    int32            ret     = 0;
    uint32           cmd = 0;
    DsMac_m          dsmac;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2dflt_addr);
    SYS_L2_FID_CHECK(l2dflt_addr->fid);
    SYS_USW_CID_CHECK(lchip,l2dflt_addr->cid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "fid :%d\n", l2dflt_addr->fid);

    if (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_UNKOWN_UCAST_DROP))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if (CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_UNKOWN_MCAST_DROP))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }
    if (!DRV_FROM_AT(lchip) && NULL != l2dflt_addr->xdata)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;
    }

    if (DRV_FROM_TMM(lchip) && (l2dflt_addr->cid > SYS_DEFAULT_ENTRY_MAX_CID))
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "categoryId is out of range!  categoryId = %d\n", l2dflt_addr->cid);
        return CTC_E_INVALID_PARAM;
    }

    L2_LOCK;

    fid = _sys_usw_l2_fid_node_lkup(lchip, l2dflt_addr->fid);
    if (NULL == fid)
    {
        ret = CTC_E_NOT_EXIST;
        goto error_0;
    }

    if( l2dflt_addr->l2mc_grp_id && l2dflt_addr->l2mc_grp_id != fid->mc_gid)
    {
        uint32 max_ex_nhid = 0;
        uint32 nh_id = 0;

        CTC_ERROR_GOTO(sys_usw_nh_get_mcast_nh(lchip, l2dflt_addr->l2mc_grp_id, &nh_id), ret, error_0);
        sys_usw_nh_get_max_external_nhid(lchip, &max_ex_nhid);
         /* support only share grp mode and ext nh group */
        if (nh_id >= max_ex_nhid || !fid->share_grp_en)
        {
            ret = CTC_E_NOT_SUPPORT;
            goto error_0;
        }
        fid->mc_gid = l2dflt_addr->l2mc_grp_id;
    }
    else
    {
        l2dflt_addr->l2mc_grp_id = fid->mc_gid;
    }

    cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, DEFAULT_ENTRY_INDEX(l2dflt_addr->fid), cmd, &dsmac), ret, error_0)
    if(DRV_FROM_TMM(lchip))
    {
        if (l2dflt_addr->cid)
        {
            if(GetDsMacDefault(V, xAdEn_f, &dsmac))
            {
                ret = CTC_E_NOT_SUPPORT;
                goto error_0;
            }
            SetDsMacDefault(V, categoryIdValid_f, &dsmac, 1);
            SetDsMacDefault(V, categoryId_f, &dsmac, l2dflt_addr->cid);
        }
        SetDsMacDefault(V, u_g1_dsFwd_destMap_f, &dsmac, SYS_ENCODE_MCAST_IPE_DESTMAP(l2dflt_addr->l2mc_grp_id));
        SetDsMacDefault(V, learnSource_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT)?1:0);
        SetDsMacDefault(V, conversationCheckEn_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_LEARNING_DISABLE)?1:0);
        SetDsMacDefault(V, protocolExceptionEn_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_PROTOCOL_EXCP_TOCPU)?1:0);
        SetDsMacDefault(V, srcMismatchDiscard_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_PORT_MAC_AUTH)?1:0);
        SetDsMacDefault(V, srcDiscard_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_VLAN_MAC_AUTH)?1:0);

    }
    else
    {
        SetDsMac(V, adDestMap_f, &dsmac, SYS_ENCODE_MCAST_IPE_DESTMAP(l2dflt_addr->l2mc_grp_id));
        SetDsMac(V, learnSource_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_USE_LOGIC_PORT)?1:0);
        SetDsMac(V, conversationCheckEn_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_LEARNING_DISABLE)?1:0);
        SetDsMac(V, protocolExceptionEn_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_PROTOCOL_EXCP_TOCPU)?1:0);
        SetDsMac(V, srcMismatchDiscard_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_PORT_MAC_AUTH)?1:0);
        SetDsMac(V, srcDiscard_f, &dsmac, CTC_FLAG_ISSET(l2dflt_addr->flag, CTC_L2_DFT_VLAN_FLAG_VLAN_MAC_AUTH)?1:0);
        if (l2dflt_addr->cid)
        {
            SetDsMac(V, categoryIdValid_f, &dsmac, 1);
            SetDsMac(V, categoryId_f, &dsmac, l2dflt_addr->cid);
        }
    }

    if(DRV_FROM_AT(lchip) && NULL != l2dflt_addr->xdata)
    {
        sys_l2_info_t sys;
        uint32 value[3] = {0};
        uint8 num = 0;

        if(GetDsMacDefault(V, categoryIdValid_f, &dsmac) || GetDsMacDefault(V, xAdEn_f, &dsmac))
        {
            ret = CTC_E_NOT_SUPPORT;
            goto error_0;
        }

        sal_memset(&sys, 0, sizeof(sys_l2_info_t));
        CTC_ERROR_GOTO(_sys_usw_l2_build_sys_info(lchip, L2_TYPE_DF, l2dflt_addr, &sys, 0, 0), ret, error_0);
        GetDsMacDefault(A, xAdData_f, &dsmac, value);
        for(num = 0; num < sys.xdata.info->num; num++)
        {
            SYS_USW_SET_XDATA(sys.xdata.info->fields[num].width, sys.xdata.info->fields[num].offset, sys.xdata.info->fields[num].data, value);
        }
        SetDsMacDefault(A, xAdData_f, &dsmac, value);
        SetDsMacDefault(V, xAdEn_f, &dsmac, 1);
        if(CTC_FLAG_ISSET(sys.xdata.field, SYS_DFT_XDATA_FIELD_CID))
        {
            SetDsMacDefault(V, categoryIdValid_f, &dsmac, 0);
        }
        fid->xdata_en = sys.xdata_en;
    }

    /*Set warmboot update node flag before write hardware*/
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE, 1);

    cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, DEFAULT_ENTRY_INDEX(l2dflt_addr->fid), cmd,  &dsmac), ret, error_0)
    /*add hardware success, need change software*/
    fid->flag = l2dflt_addr->flag;
    /*cid value is not equal 0, means update cid*/
    fid->cid = l2dflt_addr->cid ? l2dflt_addr->cid : fid->cid;
 error_0:
    L2_UNLOCK;
    return ret;
}

/*for linkagg hw learning or bpe to set DsMac*/
int32
sys_usw_l2_set_dsmac(uint8 lchip, uint32 gport, bool b_add)
{
    sys_l2_info_t   sys;
    DsMac_m         ds_mac;
    uint32          cmd         = 0;
    uint32          ds_mac_base = 0;
    uint32          nhid        = 0;
    uint16          dest_id     = 0;

    SYS_L2_INIT_CHECK();
    sal_memset(&ds_mac, 0, sizeof(DsMac_m));
    sal_memset(&sys, 0, sizeof(sys));

    dest_id = CTC_IS_LINKAGG_PORT(gport) ? CTC_MAP_GPORT_TO_LPORT(gport) : SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport);
    ds_mac_base = sys_usw_l2_get_dsmac_base(lchip, (CTC_IS_LINKAGG_PORT(gport) ? SYS_L2_DSMAC_BASE_TRUNK :SYS_L2_DSMAC_BASE_GPORT));

    if (b_add)
    {
        /*get nexthop id from gport*/
        sys_usw_l2_get_ucast_nh(lchip, gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_BASIC, &nhid);
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, nhid, &sys.nh_info_dsnh, 0));
        CTC_ERROR_RETURN(_sys_usw_l2_map_nh_to_sys(lchip, nhid, &sys, 0, gport, 0));

        /* write Ad */
        cmd = DRV_IOW(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(_sys_usw_l2_encode_dsmac(lchip, &ds_mac, &sys));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, ds_mac_base + dest_id, cmd, &ds_mac));
    }
    
    /* no need consider delete. actually the dsmac should be set at the initial process.
     * the reason not doing that is because linkagg nexthop is not created yet, back then.
     * Unless nexthop reserved linkagg nexthop, fdb cannot do it at the initial process.
     */

    return CTC_E_NONE;
}

int32
sys_usw_l2_default_entry_set_mac_auth(uint8 lchip, uint16 fid, bool enable)
{
    uint16 ad_index = 0;
    uint32 cmd = 0;
    uint32 value = (enable ? 1 : 0 );

    SYS_L2_INIT_CHECK();
    ad_index = DEFAULT_ENTRY_INDEX(fid);

    cmd = DRV_FROM_TMM(lchip) ? DRV_IOW(DsMacDefault_t, DsMacDefault_macSaExceptionEn_f) : DRV_IOW(DsMac_t, DsMac_macSaExceptionEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &value));
    return CTC_E_NONE;
}

int32
sys_usw_l2_default_entry_get_mac_auth(uint8 lchip, uint16 fid, bool* enable)
{
    uint16 ad_index = 0;
    uint32 cmd = 0;
    uint32  value = 0;

    SYS_L2_INIT_CHECK();
    ad_index = DEFAULT_ENTRY_INDEX(fid);

    cmd = DRV_FROM_TMM(lchip) ? DRV_IOR(DsMacDefault_t, DsMacDefault_macSaExceptionEn_f) : DRV_IOR(DsMac_t, DsMac_macSaExceptionEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &value));
    *enable = value ? TRUE : FALSE;

    return CTC_E_NONE;
}
int32
sys_usw_l2_fdb_set_entry_hit(uint8 lchip, ctc_l2_addr_t* l2_addr, uint8 hit)
{
    mac_lookup_result_t rslt;
    uint8 timer = 0;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "mac: %s,fid: %d  \n",
                      sys_output_mac(l2_addr->mac),
                      l2_addr->fid);
    sal_memset(&rslt, 0, sizeof(mac_lookup_result_t));

    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2_addr->mac, l2_addr->fid, &rslt));
    if (!rslt.hit)
    {
        return CTC_E_NOT_EXIST;
    }
    hit = hit ? 1:0;
    CTC_ERROR_RETURN(sys_usw_aging_get_aging_timer(lchip, SYS_AGING_DOMAIN_MAC_HASH, rslt.key_index, &timer));
    CTC_ERROR_RETURN(sys_usw_aging_set_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, rslt.key_index, timer, hit));

    return CTC_E_NONE;
}

int32
sys_usw_l2_fdb_get_entry_hit(uint8 lchip, ctc_l2_addr_t* l2_addr, uint8* hit)
{
    mac_lookup_result_t rslt;

    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(l2_addr);
    SYS_L2UC_FID_CHECK(l2_addr->fid);
    CTC_PTR_VALID_CHECK(hit);

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    sal_memset(&rslt, 0, sizeof(mac_lookup_result_t));
    CTC_ERROR_RETURN(_sys_usw_l2_acc_lookup_mac_fid(lchip, l2_addr->mac, l2_addr->fid, &rslt));
    if (!rslt.hit)
    {
        return CTC_E_NOT_EXIST;
    }
    CTC_ERROR_RETURN(sys_usw_aging_get_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, rslt.key_index, hit));

    return CTC_E_NONE;
}
int32
sys_usw_l2_dump_fdb_entry_detail(uint8 lchip, ctc_l2_fdb_query_t* pq,
        uint32 entry_cnt, uint8 need_check, void* p_file)
{
    sys_l2_detail_t* detail_info = NULL;
    uint16 index = 0;
    uint16 pending = 0;
    ctc_l2_fdb_query_rst_t query_rst;
    uint32 total_count = 0;
    sal_file_t fp = NULL;
    char* char_buffer = NULL;
    uint8 hit = 0;
    int32 ret = CTC_E_NONE;
    uint32 idx = 0;
    ctc_xdata_t* xdata_temp = NULL;
    ctc_xdata_field_t* fields = NULL;

    SYS_L2_INIT_CHECK();
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_PTR_VALID_CHECK(pq);

    sal_memset(&query_rst, 0, sizeof(ctc_l2_fdb_query_rst_t));

    if (!(pl2_usw_master[lchip]->cfg_hw_learn) &&(pq->query_hw)&&need_check)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not supported \n");
        return CTC_E_NOT_SUPPORT;

    }

    if (p_file)
    {
        fp = (sal_file_t)p_file;
        char_buffer = (char*)mem_malloc(MEM_FDB_MODULE, 128);
        if (NULL == char_buffer)
        {
            SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            ret = CTC_E_NO_MEMORY;
            goto end;
        }

        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Please read entry-file after seeing \"FDB entry have been writen!\"\n");
    }

    /* alloc memory for detail struct */
    detail_info = (sys_l2_detail_t*)mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_detail_t) * entry_cnt);
    if (NULL == detail_info)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto end;
    }

    query_rst.buffer_len = sizeof(ctc_l2_addr_t) * entry_cnt;
    query_rst.buffer = (ctc_l2_addr_t*)mem_malloc(MEM_FDB_MODULE, query_rst.buffer_len);
    if (NULL == query_rst.buffer)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto end;
    }
    xdata_temp = (ctc_xdata_t*)mem_malloc(MEM_FDB_MODULE, sizeof(ctc_xdata_t) * entry_cnt);
    if (NULL == xdata_temp)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto end;
    }
    fields = (ctc_xdata_field_t*)mem_malloc(MEM_FDB_MODULE, sizeof(ctc_xdata_field_t) * entry_cnt * SYS_FDB_MAX_XDATA_FIELD_NUM);
    if (NULL == fields)
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto end;
    }

    sal_memset(query_rst.buffer, 0, query_rst.buffer_len);
    sal_memset(xdata_temp, 0, sizeof(ctc_xdata_t) * entry_cnt);
    sal_memset(fields, 0, sizeof(ctc_xdata_field_t) * entry_cnt * SYS_FDB_MAX_XDATA_FIELD_NUM);

    for(index = 0; index < entry_cnt; index++)
    {
        query_rst.buffer[index].xdata = xdata_temp + index;
        query_rst.buffer[index].xdata->fields = fields + index * SYS_FDB_MAX_XDATA_FIELD_NUM;
    }

    if (p_file)
    {
        sal_fprintf(fp, "%-10s: %s \n", "Key Table",(pq->fid==0xffff)?"DsFibMacBlackHoleHashKey":"DsFibHost0MacHashKey");
        sal_fprintf(fp, "%-10s: DsMac \n", "Ad Table");
        sal_fprintf(fp, "\n");

        sal_fprintf(fp, "%-12s%-12s%-18s%-9s%-9s%-10s%-11s%-13s%-8s\n", "KEY-INDEX", "AD-INDEX", "MAC", "FID", "GPORT", "Static", "Pending", "Flag", "Hit");
        sal_fprintf(fp, "-------------------------------------------------------------------------------------------------\n");
    }
    else
    {

		SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s: %s \n", "Key Table", (pq->fid==0xffff)?"DsFibMacBlackHoleHashKey":"DsFibHost0MacHashKey" );
	    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s: DsMac \n", "Ad Table");
	    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");

		SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-12s%-12s%-18s%-9s%-9s%-10s%-11s%-13s%-8s\n", "KEY-INDEX", "AD-INDEX", "MAC", "FID", "GPORT", "Static", "Pending", "Flag", "Hit");
		SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------------------------------------\n");
    }

    do
    {
        pq->count = 0;
        sal_memset(detail_info, 0, sizeof(sys_l2_detail_t) * entry_cnt);
        query_rst.start_index = query_rst.next_query_index;

        CTC_ERROR_GOTO(_sys_usw_l2_get_fdb_entry_detail(lchip, pq, &query_rst, detail_info), ret, end);
        for (index = 0; index < pq->count; index++)
        {
            hit = 0;
            if (query_rst.buffer[index].fid != DONTCARE_FID)
            {
                CTC_ERROR_DUMP(sys_usw_aging_get_aging_status(lchip, SYS_AGING_DOMAIN_MAC_HASH, detail_info[index].key_index, &hit));
            }

            if (p_file)
            {
                sal_sprintf(char_buffer, "0x%-10x", detail_info[index].key_index);
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "0x%-8x", detail_info[index].ad_index);
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "%.4x.%.4x.%.4x%4s", sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[0]),
                            sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[2]),
                            sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[4]),
                            " ");

                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "%.4d     ", query_rst.buffer[index].fid);
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "0x%.4x   ", query_rst.buffer[index].gport);
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "%-10s",
                                          (CTC_FLAG_ISSET(detail_info[index].flag, CTC_L2_FLAG_IS_STATIC) ? "Yes" : "No"));
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "%-6s", (detail_info[index].pending) ? "Y" : "N");
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), "     0x%.8x", detail_info[index].flag);
                sal_sprintf((char_buffer + sal_strlen(char_buffer)), " %3s\n", (hit) ? "Y" : "N");
                sal_fprintf(fp, "%s", char_buffer);
                sal_memset(char_buffer, 0, 128);
                if(query_rst.buffer[index].xdata && 0 != query_rst.buffer[index].xdata->num)
                {
                    sal_fprintf(fp, "-------------------------------------------------------------------------------------------------\n");
                    sal_fprintf(fp, "%-10s  \n", "Xdata Info :");
                    sal_fprintf(fp, "%-10s   %-10s   %-10s\n", "Src-offset", "Width", "Value");
                    for(idx = 0; idx < query_rst.buffer[index].xdata->num; idx++)
                    {
                        sal_sprintf((char_buffer + sal_strlen(char_buffer)), "0x%-8x   ", query_rst.buffer[index].xdata->fields[idx].offset);
                        sal_sprintf((char_buffer + sal_strlen(char_buffer)), "0x%-8x   ", query_rst.buffer[index].xdata->fields[idx].width);
                        sal_sprintf((char_buffer + sal_strlen(char_buffer)), "0x%-8x   \n", query_rst.buffer[index].xdata->fields[idx].data);
                        sal_fprintf(fp, "%s", char_buffer);
                        sal_memset(char_buffer, 0, 128);
                    }
                }
            }
            else
            {
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-10x", detail_info[index].key_index);
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%-10x", detail_info[index].ad_index);
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%.4x.%.4x.%.4x%4s", sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[0]),
                            sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[2]),
                            sal_ntohs(*(unsigned short*)&query_rst.buffer[index].mac[4]),
                            " ");

                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%.4d     ", query_rst.buffer[index].fid);

                if (SYS_RSV_PORT_TO_CPU == CTC_MAP_GPORT_TO_LPORT(query_rst.buffer[index].gport) && !query_rst.buffer[index].is_logic_port)
                {
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-9s", "CPU");
                }
                else
                {
                    if (pq->query_flag == CTC_L2_FDB_ENTRY_MCAST)
                    {
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %3s  ", "-     ");
                    }
                    else
                    {
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "0x%.4x   ", query_rst.buffer[index].gport);
                    }
                }
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s", CTC_FLAG_ISSET(detail_info[index].flag, CTC_L2_FLAG_IS_STATIC) ? "Yes" : "No");
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-6s", (detail_info[index].pending) ? "Y" : "N");
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "     0x%.8x", detail_info[index].flag);
                SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %3s\n", (hit) ? "Y" : "N");
                if(query_rst.buffer[index].xdata && 0 != query_rst.buffer[index].xdata->num)
                {
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------------------------------------\n");
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s  \n", "Xdata Info :");
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%-10s   %-10s   %-10s\n", "Src-offset", "Width", "Value");
                    for(idx = 0; idx < query_rst.buffer[index].xdata->num; idx++)
                    {
                        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"0x%-8x   0x%-8x   0x%-8x\n", query_rst.buffer[index].xdata->fields[idx].offset, 
                                    query_rst.buffer[index].xdata->fields[idx].width, query_rst.buffer[index].xdata->fields[idx].data);
                    }
                }
            }

            if (detail_info[index].pending)
            {
                pending ++;
            }

            total_count++;
            sal_task_sleep(100);

            sal_memset(&detail_info[index], 0, sizeof(sys_l2_detail_t));
        }

    }
    while (query_rst.is_end == 0);

    if (p_file)
    {
        sal_fprintf(fp,"-------------------------------------------------------------------------------------------------\n");
        sal_fprintf(fp,"Total Entry Num: %d\n", total_count);
        sal_fprintf(fp,"Pending Entry Num: %d\n", pending);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "FDB entry have been writen\n");
    }
    else
    {
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------------------------------------\n");
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Total Entry Num: %d\n", total_count);
        SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Pending Entry Num: %d\n", pending);
    }
end:
    if (detail_info)
    {
        mem_free(detail_info);
    }
    if (char_buffer)
    {
        mem_free(char_buffer);
    }
    if(query_rst.buffer)
    {
        mem_free(query_rst.buffer);
    }
    if(xdata_temp)
    {
        mem_free(xdata_temp);
    }
    if(fields)
    {
        mem_free(fields);
    }
    return ret;
}

#define __WARM_BOOT__
int32
_sys_usw_l2_wb_init(uint8 lchip)
{
    ctc_wb_appid_t  appid;
    sal_memset(&appid, 0, sizeof(appid));

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER) ;
    appid.entry_num = SYS_WB_FEATURE_MASTER_NUM;
    appid.entry_size  = sizeof(sys_wb_l2_master_t);
    appid.rt_en = 0;
   ctc_wb_add_appid(lchip,&appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB) ;
    appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_STATIC_FDB);
    appid.entry_size  = sizeof(sys_wb_l2_fdb_t);
    appid.rt_en = 0;
   ctc_wb_add_appid(lchip,&appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID) ;
    appid.entry_num = pl2_usw_master[lchip]->cfg_vport_num;
    appid.entry_size  = sizeof(sys_wb_l2_vport_2_nhid_t);
    appid.rt_en = 0;
   ctc_wb_add_appid(lchip,&appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE) ;
    appid.entry_num = pl2_usw_master[lchip]->cfg_max_fid+1;
    appid.entry_size  = sizeof(sys_wb_l2_fid_node_t);
    appid.rt_en = 0;
   ctc_wb_add_appid(lchip, &appid);

   appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MCAST) ;
   appid.entry_num = sys_usw_ftm_get_spec(lchip, CTC_FTM_SPEC_L2MC);
   appid.entry_size  = sizeof(sys_wb_ftm_ad_t);
   appid.rt_en = 0;
   ctc_wb_add_appid( lchip, &appid);

   return CTC_E_NONE;
}

int32
_sys_usw_l2_wb_mapping_fid(sys_wb_l2_fid_node_t *p_wb_fid, sys_l2_fid_node_t *p_fid, uint8 sync)
{
    if (sync)
    {
        p_wb_fid->fid = p_fid->fid;
        p_wb_fid->flag = p_fid->flag;
        p_wb_fid->mc_gid = p_fid->mc_gid;
        p_wb_fid->share_grp_en = p_fid->share_grp_en;
        p_wb_fid->cid = p_fid->cid;
        p_wb_fid->xdata_en = p_fid->xdata_en;
        p_wb_fid->rsv[0] = 0;
        p_wb_fid->rsv[1] = 0;
    }
    else
    {
        p_fid->fid = p_wb_fid->fid;
        p_fid->flag = p_wb_fid->flag;
        p_fid->mc_gid = p_wb_fid->mc_gid;
        p_fid->share_grp_en = p_wb_fid->share_grp_en;
        p_fid->cid = p_wb_fid->cid;
        p_fid->xdata_en = p_wb_fid->xdata_en;
    }

    return CTC_E_NONE;
}
int32
_sys_usw_l2_wb_sync_fid_func(void* array_data, uint32 index, void *user_data)
{
    uint32 max_entry_cnt = 0;
    sys_l2_fid_node_t *p_fid = (sys_l2_fid_node_t *)array_data;
    sys_wb_l2_fid_node_t  *p_wb_fid;
    sys_traverse_t *traversal_data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t *)traversal_data->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = traversal_data->value1;
#endif

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    max_entry_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    p_wb_fid = (sys_wb_l2_fid_node_t *)wb_data->buffer + wb_data->valid_cnt;

    CTC_ERROR_RETURN(_sys_usw_l2_wb_mapping_fid(p_wb_fid, p_fid, 1));
    p_wb_fid->rsv1 = 0;

#if 0
    if(traversal_data->value2)
    {
        ctc_nh_info_t nh_info;
        uint32 nh_id;
        uint16 loop;
        uint16 loop1;
        ctc_mcast_nh_param_member_t* p_member;

        lchip = traversal_data->value1;
        sal_memset(&nh_info, 0, sizeof(nh_info));
        nh_info.buffer = mem_malloc(MEM_FDB_MODULE, 100*sizeof(ctc_mcast_nh_param_member_t));
        if(NULL == nh_info.buffer)
        {
            return CTC_E_NO_MEMORY;
        }
        nh_info.buffer_len = 100*sizeof(ctc_mcast_nh_param_member_t);

        CTC_ERROR_RETURN(sys_usw_nh_get_mcast_nh(lchip, p_fid->mc_gid, &nh_id));
        do{
            CTC_ERROR_RETURN(sys_usw_nh_get_mcast_member(lchip, nh_id, &nh_info));
            for(loop=0; loop < nh_info.valid_number; loop++)
            {
                p_member = nh_info.buffer+loop;
                if(p_member->member_type != CTC_NH_PARAM_MEM_BRGMC_LOCAL)
                {
                    continue;
                }

                if(p_member->gchip_id == 0x1F && p_member->port_bmp_en)
                {
                    for(loop1=0; loop1 < CTC_PORT_BITMAP_IN_WORD; loop1++)
                    {
                        p_wb_fid->linkagg_bmp[loop1] |= p_member->port_bmp[loop1];
                    }
                }
                else if(p_member->port_bmp_en)
                {
                    for(loop1=0; loop1 < CTC_PORT_BITMAP_IN_WORD; loop1++)
                    {
                        p_wb_fid->port_bmp[loop1] |= p_member->port_bmp[loop1];
                    }
                }
             }

            nh_info.start_index = nh_info.next_query_index;
        }while(!nh_info.is_end);
    }

#endif
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;

}
int32
_sys_usw_l2_wb_sync_vport2nh_func(void* array_data, uint32 index, void *user_data)
{
    uint32 max_entry_cnt = 0;
    sys_l2_vport_2_nhid_t *p_v2nhid = (sys_l2_vport_2_nhid_t *)array_data;
    sys_wb_l2_vport_2_nhid_t  *p_wb_v2nhid;
    sys_traverse_t *traversal_data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t *)traversal_data->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = traversal_data->value1;
#endif
    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    max_entry_cnt = wb_data->buffer_len  / (wb_data->key_len + wb_data->data_len);

    p_wb_v2nhid = (sys_wb_l2_vport_2_nhid_t *)wb_data->buffer + wb_data->valid_cnt;
    sal_memset(p_wb_v2nhid, 0, sizeof(sys_wb_l2_vport_2_nhid_t));

    p_wb_v2nhid->vport   = index;
    p_wb_v2nhid->nhid    = p_v2nhid->nhid;
    p_wb_v2nhid->ad_idx  = p_v2nhid->ad_idx;
    p_wb_v2nhid->ad_idx1  = p_v2nhid->ad_idx1;
    p_wb_v2nhid->use_ldp = p_v2nhid->use_ldp;
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32 _sys_usw_l2_wb_mapping_fdb(uint8 lchip, sys_wb_l2_fdb_t* p_wb_fdb, sys_l2_node_t* p_l2_node, uint8 is_sync)
{
    uint32 cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
    sys_l2_ad_t l2_ad;
    sys_l2_ad_t* p_l2_ad_get = NULL;
    DsMac_m dsmac;
    if(is_sync)
    {
        sal_memcpy(&p_wb_fdb->mac, &p_l2_node->mac, sizeof(mac_addr_t));
        p_wb_fdb->fid = p_l2_node->fid;
        p_wb_fdb->flag = p_l2_node->flag;
        p_wb_fdb->ad_index = p_l2_node->adptr->index;
        p_wb_fdb->bind_nh = p_l2_node->bind_nh;
        p_wb_fdb->nh_id = p_l2_node->nh_id;
        p_wb_fdb->rsv_ad = p_l2_node->rsv_ad;
        p_wb_fdb->rsv1 = 0;
    }
    else
    {
        sys_nh_info_dsnh_t nh_info;

        sal_memset(&l2_ad, 0, sizeof(l2_ad));
        sal_memcpy(&p_l2_node->mac, &p_wb_fdb->mac, sizeof(mac_addr_t));

        p_l2_node->fid = p_wb_fdb->fid;
        p_l2_node->flag = p_wb_fdb->flag;
        p_l2_node->bind_nh = p_wb_fdb->bind_nh;
        p_l2_node->nh_id = p_wb_fdb->nh_id;
        p_l2_node->rsv_ad = p_wb_fdb->rsv_ad;

        sal_memset(&nh_info, 0, sizeof(nh_info));
        if (p_l2_node->nh_id)
        {
            CTC_ERROR_DUMP(sys_usw_nh_get_nhinfo(lchip, p_l2_node->nh_id, &nh_info, 0));
        }
        p_l2_node->ecmp_valid = nh_info.ecmp_valid || nh_info.is_ecmp_intf;
        p_l2_node->aps_valid = nh_info.aps_en;

        l2_ad.index = p_wb_fdb->ad_index;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, l2_ad.index, cmd, &dsmac));
        if (p_l2_node->rsv_ad)
        {
            MALLOC_ZERO(MEM_FDB_MODULE, p_l2_node->adptr, sizeof(sys_l2_ad_t));
            if(NULL == p_l2_node->adptr)
            {
                return CTC_E_NO_MEMORY;
            }
        }
        else
        {
            /*vxlan ldp tunnel update*/
            if ((nh_info.nh_entry_type == SYS_NH_TYPE_OVERLAY || nh_info.bind_ldp) && nh_info.logic_port && 
                ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)) || DRV_IS_TSINGMA(lchip)))
            {
                l2_ad.param.ldp = nh_info.logic_port;
            }
            if (nh_info.nh_entry_type == SYS_NH_TYPE_SRV6)
            {
                l2_ad.param.srv6_nhid = p_l2_node->nh_id;
                l2_ad.param.ldp = SYS_COM_LDP_SRH_ID(nh_info.tunnel_id);
            }
            l2_ad.param.ds_mac = &dsmac;
            CTC_ERROR_RETURN(_sys_usw_l2_dsmac_spool_add(lchip, &l2_ad, &p_l2_ad_get));
            p_l2_node->adptr = p_l2_ad_get;
        }
    }

    return CTC_E_NONE;
}

int32
_sys_usw_l2_wb_sync_fdb_func(sys_l2_node_t *p_node, void *user_data)
{
    uint32 max_entry_cnt = 0;
    sys_wb_l2_fdb_t  *p_wb_fdb;
    sys_traverse_t *traversal_data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t *)(traversal_data->data);
    uint8 lchip = (uint8)traversal_data->value1;

    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    max_entry_cnt = wb_data->buffer_len  / (wb_data->key_len + wb_data->data_len);

    p_wb_fdb = (sys_wb_l2_fdb_t *)wb_data->buffer + wb_data->valid_cnt;

    CTC_ERROR_RETURN(_sys_usw_l2_wb_mapping_fdb(lchip, p_wb_fdb, p_node, 1));
    if (++wb_data->valid_cnt == max_entry_cnt)
    {
        CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}


int32
sys_usw_l2_fdb_wb_sync(uint8 lchip,uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_traverse_t user_data = {0};
    sys_wb_l2_master_t*  p_wb_l2_master = NULL;

    sal_memset(&user_data, 0, sizeof(user_data));

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);

    L2_LOCK;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_L2_SUBID_MASTER)
    {
        /*syncup fdb_matser*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_l2_master_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER);

        p_wb_l2_master = (sys_wb_l2_master_t *)wb_data.buffer;

        p_wb_l2_master->lchip = lchip;
        p_wb_l2_master->l2mc_count = pl2_usw_master[lchip]->l2mc_count;
        p_wb_l2_master->ad_index_drop = pl2_usw_master[lchip]->ad_index_drop;
        p_wb_l2_master->cfg_vport_num = pl2_usw_master[lchip]->cfg_vport_num;
        p_wb_l2_master->cfg_hw_learn = pl2_usw_master[lchip]->cfg_hw_learn;
        p_wb_l2_master->static_fdb_limit = pl2_usw_master[lchip]->static_fdb_limit;
        p_wb_l2_master->cfg_max_fid = pl2_usw_master[lchip]->cfg_max_fid;
        p_wb_l2_master->vp_alloc_ad_en = pl2_usw_master[lchip]->vp_alloc_ad_en;
        p_wb_l2_master->search_depth = pl2_usw_master[lchip]->search_depth;
        p_wb_l2_master->version = SYS_WB_VERSION_L2;
        p_wb_l2_master->rsv1 = 0;
        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_L2_SUBID_FID_NODE)
    {
        /*syncup fdb fid*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_l2_fid_node_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE);
        user_data.data = &wb_data;
        user_data.value1 = lchip;

        CTC_ERROR_GOTO(ctc_vector_traverse2(pl2_usw_master[lchip]->fid_vec, 0, _sys_usw_l2_wb_sync_fid_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_L2_SUBID_VPORT_2_NHID)
    {
        /*sync nhid of logic port*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_l2_vport_2_nhid_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID);
        user_data.data = &wb_data;
        user_data.value1 = lchip;

        CTC_ERROR_GOTO(ctc_vector_traverse2(pl2_usw_master[lchip]->vport2nh_vec, 0, _sys_usw_l2_wb_sync_vport2nh_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_L2_SUBID_FDB)
    {
        /*syncup fdb*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_l2_fdb_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB);
        user_data.data = &wb_data;
        user_data.value1 = lchip;

        CTC_ERROR_GOTO(ctc_hash_traverse(pl2_usw_master[lchip]->fdb_hash, (hash_traversal_fn) _sys_usw_l2_wb_sync_fdb_func, (void *)&user_data), ret, done);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB);
    }
     if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_L2_SUBID_MCAST)
     {
        sys_usw_ftm_l2mc_wb_sync(lchip, app_id);
     }
done:
    L2_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32
sys_usw_l2_fdb_wb_restore(uint8 lchip)
{
    uint32 entry_cnt = 0;
    int32 ret = CTC_E_NONE;
    ctc_wb_query_t wb_query;
    sys_wb_l2_master_t  wb_l2_master;
    sys_wb_l2_master_t  *p_wb_l2_master = &wb_l2_master;
    sys_l2_node_t *p_l2_node = NULL;
    sys_wb_l2_fdb_t  wb_fdb;
    sys_wb_l2_fdb_t  *p_wb_fdb = &wb_fdb;
    sys_l2_fid_node_t *p_fid;
    sys_wb_l2_fid_node_t  wb_fid;
    sys_wb_l2_fid_node_t *p_wb_fid = &wb_fid;
    sys_l2_vport_2_nhid_t *p_v2nh;
    sys_wb_l2_vport_2_nhid_t  wb_v2nh;
    sys_wb_l2_vport_2_nhid_t *p_wb_v2nh = &wb_v2nh;
    uint32  loop = 0;
    uint32  cmd = 0;
    uint32  value = 0;
    DsFibMacBlackHoleHashKey_m DsFibMacBlackHoleHashKey;
    sys_nh_info_dsnh_t nh_info;
    sys_l2_ad_t l2_ad;
    DsMac_m dsmac;

    SYS_L2_INIT_CHECK();
    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    /* set default value*/
    sal_memset(p_wb_l2_master, 0, sizeof(sys_wb_l2_master_t));
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_l2_master_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER);

    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);

    /*restore fdb_master*/
    if (wb_query.valid_cnt == 1)
    {
        sal_memcpy((uint8*)p_wb_l2_master, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);

        if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_L2, p_wb_l2_master->version))
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto done;
        }

        if ( (pl2_usw_master[lchip]->cfg_vport_num > p_wb_l2_master->cfg_vport_num)
            || (pl2_usw_master[lchip]->cfg_hw_learn != p_wb_l2_master->cfg_hw_learn)
        || (pl2_usw_master[lchip]->static_fdb_limit != p_wb_l2_master->static_fdb_limit)
        || (pl2_usw_master[lchip]->cfg_max_fid > p_wb_l2_master->cfg_max_fid)
        || (pl2_usw_master[lchip]->vp_alloc_ad_en != p_wb_l2_master->vp_alloc_ad_en))
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto done;
        }
        pl2_usw_master[lchip]->l2mc_count = p_wb_l2_master->l2mc_count;
        pl2_usw_master[lchip]->ad_index_drop = p_wb_l2_master->ad_index_drop;
        pl2_usw_master[lchip]->search_depth = p_wb_l2_master->search_depth;
        /* add static spool for drop ad*/
        sal_memset(&l2_ad, 0, sizeof(l2_ad));
        sal_memset(&dsmac, 0, sizeof(DsMac_m));
        SetDsMac(V, dsFwdPtr_f, &dsmac, SYS_FDB_DISCARD_FWD_PTR);
        SetDsMac(V, protocolExceptionEn_f, &dsmac, 1);
        SetDsMac(V, isStatic_f, &dsmac, 1);
        SetDsMac(V, stormCtlEn_f, &dsmac, 1);
        SetDsMac(V, fastLearningEn_f, &dsmac, 1);
        l2_ad.index = pl2_usw_master[lchip]->ad_index_drop;
        l2_ad.param.ds_mac = &dsmac;
        l2_ad.param.lchip = lchip;
        CTC_ERROR_RETURN(ctc_spool_static_add(pl2_usw_master[lchip]->ad_spool, &l2_ad));

        cmd = DRV_IOR(DsFibMacBlackHoleHashKey_t, DRV_ENTRY_FLAG);
        for (loop = 0; loop < SYS_L2_MAX_BLACK_HOLE_ENTRY; loop++)
        {
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, loop, cmd, &DsFibMacBlackHoleHashKey), ret, done);
            value = GetDsFibMacBlackHoleHashKey(V, valid_f, &DsFibMacBlackHoleHashKey);
            if (value)
            {
                CTC_BMP_SET(pl2_usw_master[lchip]->mac_fdb_bmp, loop);
                value = GetDsFibMacBlackHoleHashKey(V, dsAdIndex_f, &DsFibMacBlackHoleHashKey);
                ret = sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 1, 1, value);
                if (ret)
                {
                    SYS_FDB_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "wb ftm alloc failed,  line=%d\n", __LINE__);
                    goto done;
                }
            }
        }
    }

    /*restore fdb */
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_l2_fdb_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FDB);
    /* set default value*/
    sal_memset(p_wb_fdb, 0, sizeof(sys_wb_l2_fdb_t));

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_fdb, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        p_l2_node = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_node_t));
        if (NULL == p_l2_node)
        {
            ret = CTC_E_NO_MEMORY;

            goto done;
        }
        sal_memset(p_l2_node, 0, sizeof(sys_l2_node_t));

        ret = _sys_usw_l2_wb_mapping_fdb(lchip, p_wb_fdb, p_l2_node, 0);
        if (ret)
        {
            continue;
        }

        if (p_l2_node->bind_nh)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_l2_node, 1, 0, 0);
        }
        /*add to soft table*/
        ctc_hash_insert(pl2_usw_master[lchip]->fdb_hash, p_l2_node);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

     /*restore fdb fid*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_l2_fid_node_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_FID_NODE);
    /* set default value*/
    sal_memset(p_wb_fid, 0, sizeof(sys_wb_l2_fid_node_t));

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_fid, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;
#if 0
        if(p_wb_fid->recover_hw_en)
        {
            ctc_l2dflt_addr_t l2dflt;
            uint16            loop;
            uint8             gchip;
            sal_memset(&l2dflt, 0, sizeof(l2dflt));

            l2dflt.fid = p_wb_fid->fid;
            l2dflt.cid = p_wb_fid->cid;
            l2dflt.flag = p_wb_fid->flag;
            l2dflt.l2mc_grp_id = p_wb_fid->mc_gid;
            l2dflt.share_grp_en = p_wb_fid->share_grp_en;
            CTC_ERROR_GOTO(sys_usw_l2_add_default_entry(lchip, &l2dflt), ret, done);

            CTC_ERROR_GOTO(sys_usw_get_gchip_id(lchip, &gchip), ret, done);
            for(loop=0; loop < MAX_PORT_NUM_PER_CHIP; loop++)
            {
                if(CTC_BMP_ISSET(p_wb_fid->port_bmp, loop))
                {
                    l2dflt.member.mem_port = CTC_MAP_LPORT_TO_GPORT(gchip, loop);
                    CTC_ERROR_GOTO(sys_usw_l2_add_port_to_default_entry(lchip, &l2dflt), ret, done);
                }
            }
            for(loop=0; loop < MAX_PORT_NUM_PER_CHIP; loop++)
            {
                if(CTC_BMP_ISSET(p_wb_fid->linkagg_bmp, loop))
                {
                    l2dflt.member.mem_port = CTC_MAP_LPORT_TO_GPORT(0x1F, loop);
                    CTC_ERROR_GOTO(sys_usw_l2_add_port_to_default_entry(lchip, &l2dflt), ret, done);
                }
            }
            continue;
        }
#endif
        p_fid = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_fid_node_t));
        if (NULL == p_fid)
        {
            ret = CTC_E_NO_MEMORY;

            goto done;
        }
        sal_memset(p_fid, 0, sizeof(sys_l2_fid_node_t));

        ret = _sys_usw_l2_wb_mapping_fid(p_wb_fid, p_fid, 0);
        if (ret)
        {
            continue;
        }

        /*add to soft table*/
        ctc_vector_add(pl2_usw_master[lchip]->fid_vec, p_fid->fid, p_fid);
        pl2_usw_master[lchip]->def_count++;
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    /*restore nhid of logic port*/
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_l2_vport_2_nhid_t, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_VPORT_2_NHID);
    /* set default value*/
    sal_memset(p_wb_v2nh, 0, sizeof(sys_wb_l2_vport_2_nhid_t));

    CTC_WB_QUERY_ENTRY_BEGIN((&wb_query));
        sal_memcpy((uint8*)p_wb_v2nh, (uint8*)(wb_query.buffer) + entry_cnt * (wb_query.key_len + wb_query.data_len), wb_query.key_len + wb_query.data_len);
        entry_cnt++;

        p_v2nh = mem_malloc(MEM_FDB_MODULE, sizeof(sys_l2_vport_2_nhid_t));
        if (NULL == p_v2nh)
        {
            ret = CTC_E_NO_MEMORY;

            goto done;
        }
        sal_memset(p_v2nh, 0, sizeof(sys_l2_vport_2_nhid_t));

        p_v2nh->ad_idx  = p_wb_v2nh->ad_idx;
        p_v2nh->nhid    = p_wb_v2nh->nhid;
        p_v2nh->use_ldp = p_wb_v2nh->use_ldp;
        p_v2nh->ad_idx1 = p_wb_v2nh->ad_idx1;
        /*recover nh bind */
        sal_memset(&nh_info, 0, sizeof(sys_nh_info_dsnh_t));
        CTC_ERROR_DUMP(sys_usw_nh_get_nhinfo(lchip, p_v2nh->nhid, &nh_info, 0));
        if (!nh_info.data && !nh_info.dsfwd_valid)
        {
            _sys_usw_l2_bind_nexthop(lchip, p_v2nh, 1, 1, p_wb_v2nh->vport);
        }
        if (pl2_usw_master[lchip]->vp_alloc_ad_en)
        {
            ret = sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 0, 1, p_v2nh->ad_idx);
            if (ret)
            {
                CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "alloc dsmac profile id from position %u error! ret: %d.\n",  p_v2nh->ad_idx, ret);
                mem_free(p_v2nh);
                goto done;
            }
        }
        if (p_v2nh->ad_idx1)
        {
            sys_l2_ad_t l2_ad;
            sys_l2_ad_param_t l2_ad_param;
            sal_memset(&l2_ad_param, 0, sizeof(sys_l2_ad_param_t));
            sal_memset(&l2_ad, 0, sizeof(sys_l2_ad_t));
            l2_ad_param.lchip =lchip;
            l2_ad.index = p_v2nh->ad_idx1;
            CTC_ERROR_GOTO(_sys_usw_l2_ad_spool_alloc_index(&l2_ad, &l2_ad_param), ret, done);
        }
        /*add to soft table*/
        ctc_vector_add(pl2_usw_master[lchip]->vport2nh_vec, p_wb_v2nh->vport, p_v2nh);
    CTC_WB_QUERY_ENTRY_END((&wb_query));

    sys_usw_ftm_l2mc_wb_restore(lchip);

done:
    drv_set_warmboot_status(lchip, CTC_WB_STATUS_RELOADING);
    CTC_WB_FREE_BUFFER(wb_query.buffer);
    return ret;
}

/*for stacking*/
int32
sys_usw_l2_wb_sync_rchip_rsv_ad(uint8 lchip, uint16** rchip_ad_rsv)
{
    SYS_L2_INIT_CHECK();

    L2_LOCK;

    *rchip_ad_rsv = pl2_usw_master[lchip]->rchip_ad_rsv;

    L2_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_l2_wb_restore_rchip_rsv_ad(uint8 lchip, uint16** rchip_ad_rsv)
{
    uint32 base = 0;
    uint32 cmd = 0;
    int32 ret = CTC_E_NONE;
    uint32 loop = 0;
    FibAccelerationRemoteChipAdBase_m* fib_acceleration_ctl = NULL;

    SYS_L2_INIT_CHECK();

    fib_acceleration_ctl = (FibAccelerationRemoteChipAdBase_m*)mem_malloc(MEM_FDB_MODULE, sizeof(FibAccelerationRemoteChipAdBase_m));
    if(NULL == fib_acceleration_ctl)
    {
        return CTC_E_NO_RESOURCE;
    }
    L2_LOCK; 
    sal_memcpy(pl2_usw_master[lchip]->rchip_ad_rsv, *rchip_ad_rsv, (SYS_USW_MAX_GCHIP_CHIP_ID+1) * sizeof(uint16));
    cmd = DRV_IOR(FibAccelerationRemoteChipAdBase_t, DRV_ENTRY_FLAG);
    if(DRV_FROM_AT(lchip))
    {
        for (loop = 0; loop <= SYS_USW_MAX_GCHIP_CHIP_ID; loop++)
        {
            if (pl2_usw_master[lchip]->rchip_ad_rsv[loop] == 0)
            {
                continue;
            }
            DRV_IOCTL(lchip, loop, cmd, fib_acceleration_ctl);
            base = GetFibAccelerationRemoteChipAdBase(V, remoteChipAdBase_f, fib_acceleration_ctl);
            CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 1, pl2_usw_master[lchip]->rchip_ad_rsv[loop]&0x3FFF, base << 6), ret, error0);
        }
    }
    else
    {
        DRV_IOCTL(lchip, 0, cmd, fib_acceleration_ctl);
        for (loop = 0; loop <= SYS_USW_MAX_GCHIP_CHIP_ID; loop++)
        {
            if (pl2_usw_master[lchip]->rchip_ad_rsv[loop] == 0)
            {
                continue;
            }
            base = GetFibAccelerationRemoteChipAdBase(V, array_0_remoteChipAdBase_f+loop, fib_acceleration_ctl);
            CTC_ERROR_GOTO(sys_usw_ftm_alloc_table_offset_from_position(lchip, DsMac_t, 1, pl2_usw_master[lchip]->rchip_ad_rsv[loop]&0x3FFF, base << 6), ret, error0);
        }
    }

error0:
    L2_UNLOCK;
    mem_free(fib_acceleration_ctl);

    return ret;
}

STATIC int32
_sys_usw_l2_dump_spool_db(void *node, void* user_date)
{
    sys_traverse_t* p_traverse = (sys_traverse_t*)user_date;
    uint32*   p_spool_cnt = (uint32*)p_traverse->data1;
    sal_file_t p_f = (sal_file_t)p_traverse->data;
    ctc_spool_node_t* p_node = (ctc_spool_node_t*)node;
    sys_l2_ad_t* l2_ad = (sys_l2_ad_t*)p_node->data;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = p_traverse->value1;
#endif
    if(0xFFFFFFFF == p_node->ref_cnt)
    {
        SYS_DUMP_DB_LOG(p_f, "%-20u %-20u %-20s\n", *p_spool_cnt, l2_ad->index, "Static");
    }
    else
    {
        SYS_DUMP_DB_LOG(p_f, "%-20u %-20u %-20u\n", *p_spool_cnt, l2_ad->index, p_node->ref_cnt);
    }
    (*p_spool_cnt)++;
    return CTC_E_NONE;
}

int32
sys_usw_l2_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    uint32 loop = 0;
    uint8  first_flag = 0;
    sys_traverse_t  param;
    uint32  spool_cnt = 1;

    SYS_L2_INIT_CHECK();
    L2_LOCK;
    SYS_DUMP_DB_LOG(p_f, "%s\n", "# L2");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","L2 mcast count", pl2_usw_master[lchip]->l2mc_count);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Default entry count", pl2_usw_master[lchip]->def_count);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Ad index for discard", pl2_usw_master[lchip]->ad_index_drop);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Default entry base", pl2_usw_master[lchip]->dft_entry_base);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Logic port number for learning", pl2_usw_master[lchip]->cfg_vport_num);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Hardware learning enable", pl2_usw_master[lchip]->cfg_hw_learn);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Mac limit include static fdb", pl2_usw_master[lchip]->static_fdb_limit);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Max fid value", pl2_usw_master[lchip]->cfg_max_fid);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Enable trie sort", pl2_usw_master[lchip]->trie_sort_en);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Reserve ad for logic port", !pl2_usw_master[lchip]->vp_alloc_ad_en);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","L2 software db count", pl2_usw_master[lchip]->fdb_hash->count);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","L2 search_depth", pl2_usw_master[lchip]->search_depth);
    SYS_DUMP_DB_LOG(p_f, "%-36s: %u\n","Station move no learn", pl2_usw_master[lchip]->station_move_no_learn);
    SYS_DUMP_DB_LOG(p_f, "%-36s:\n","Bitmap for mac based fdb");
    for(loop=0; loop < SYS_L2_MAX_BLACK_HOLE_ENTRY/32; loop++)
    {
        SYS_DUMP_DB_LOG(p_f, "%-32s%-4u: 0x%0x\n","", loop, pl2_usw_master[lchip]->mac_fdb_bmp[loop]);
    }

    for(loop=0; loop < SYS_USW_MAX_GCHIP_CHIP_ID; loop++)
    {
        if(0 == pl2_usw_master[lchip]->rchip_ad_rsv[loop])
        {
            continue;
        }

        if(0 == first_flag)
        {
            SYS_DUMP_DB_LOG(p_f, "%-36s:\n","Reserved ad base for remote chip");
            first_flag = 0;

        }
        SYS_DUMP_DB_LOG(p_f, "%-36sgchip%-4u : %-10u","", loop, (pl2_usw_master[lchip]->rchip_ad_rsv[loop]&0x3FFF));
    }
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "\n");

    sal_memset(&param, 0, sizeof(param));
    param.data = (void*)p_f;
    param.data1 = (void*)&spool_cnt;
    param.value1 = lchip;

    SYS_DUMP_DB_LOG(p_f, "Spool type: %-15s\n","L2 DsMac Spool");
    SYS_DUMP_DB_LOG(p_f, "%-20s: DsMac \n", "Key table");
    SYS_DUMP_DB_LOG(p_f, "%-20s %-20s %-20s\n", "Node","Index", "Ref count");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------");
    ctc_spool_traverse(pl2_usw_master[lchip]->ad_spool, (spool_traversal_fn)_sys_usw_l2_dump_spool_db , (void*)(&param));
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------");

    SYS_DUMP_DB_LOG(p_f, "\n");
    L2_UNLOCK;
    sys_usw_learning_aging_dump_db(lchip, p_f, p_dump_param);
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");
    return CTC_E_NONE;
}
#if 0
int32 sys_usw_l2_fdb_change_mem_cb(uint8 lchip, void*user_data)
{
    int32 ret = 0;
    ctc_l2_flush_fdb_t flush;
    sal_memset(&flush, 0, sizeof(flush));
    SYS_L2_INIT_CHECK();
    flush.flush_flag = CTC_L2_FDB_ENTRY_PENDING;
    flush.flush_type = CTC_L2_FDB_ENTRY_OP_ALL;
    ret = sys_usw_l2_flush_fdb(lchip, &flush);

    flush.flush_flag = CTC_L2_FDB_ENTRY_ALL;
    ret = ret ? ret : sys_usw_l2_flush_fdb(lchip, &flush);
    return ret;
}
#endif
int32 sys_usw_l2_fdb_set_search_depth(uint8 lchip, uint32 search_depth)
{
    SYS_L2_INIT_CHECK();
    if(search_depth > 255)
    {
        return CTC_E_INVALID_PARAM;
    }
    L2_LOCK;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_L2, SYS_WB_APPID_L2_SUBID_MASTER, 1);
    pl2_usw_master[lchip]->search_depth = search_depth;
    L2_UNLOCK;

    return 0;
}
int32 sys_usw_l2_fdb_get_search_depth(uint8 lchip, uint32* p_search_depth)
{
    SYS_L2_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_search_depth);
    L2_LOCK;
    *p_search_depth = pl2_usw_master[lchip]->search_depth;
    L2_UNLOCK;

    return 0;
}
int32
sys_usw_l2_fdb_init_done(uint8 lchip)
{
    uint8 chan_en = 0;
    if (NULL == pl2_usw_master[lchip])
    {
        return CTC_E_NONE;
    }
    sys_usw_dma_get_chan_en(lchip, SYS_DMA_HASHKEY_CHAN_ID, &chan_en);
    if(TRUE == sys_usw_l2_fdb_trie_sort_en(lchip) && chan_en)
    {
        CTC_ERROR_RETURN(sys_usw_fdb_sort_init(lchip));
    }
    return CTC_E_NONE;
}

#if defined(DUET2)
STATIC int32
_sys_usw_l2_get_dstmp_profile_cb(void* p_bucket_node, uint32 cur_hash_node_id, uint32 cur_list_id, void* user_data)
{
    ctc_hash_bucket_t* bucket_node = (ctc_hash_bucket_t*)p_bucket_node;
    sys_l2_node_t* p_l2_node = NULL;
    sys_l2_destmap_profile_fdb_t* user_info = (sys_l2_destmap_profile_fdb_t*)user_data;
    uint8 lchip = user_info->lchip;
    ctc_l2_addr_t* p_user_addr_buf = NULL;
    sys_l2_info_t l2_info_sys;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    DsMac_m dsmac;
    sal_memset(&l2_info_sys, 0, sizeof(sys_l2_info_t));

    if (user_info->pr->buffer_len <  sizeof(ctc_l2_addr_t))
    {
         return CTC_E_NO_MEMORY;
    }

    p_l2_node = (sys_l2_node_t*)(bucket_node->data);
    if(p_l2_node && p_l2_node->use_destmap_profile)
    {
        /*get sw data to user_buf*/
        cmd = DRV_IOR(DsMac_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_l2_node->adptr->index, cmd, &dsmac));
        sys_usw_l2_decode_dsmac(lchip, &l2_info_sys, p_l2_node->adptr->index, &dsmac);

        if (user_info->pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_VID)
        {
            if(user_info->pq->fid != p_l2_node->fid)
            {
                ret =  CTC_E_NONE;
                goto done;
            }

        }
        else if (user_info->pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT)
        {
            if(l2_info_sys.is_logic_port != user_info->pq->use_logic_port || user_info->pq->gport != l2_info_sys.addr.l2_addr.gport)
            {
                ret =  CTC_E_NONE;
                goto done;
            }
        }
        else if (user_info->pq->query_type == CTC_L2_FDB_ENTRY_OP_BY_PORT_VLAN)
        {
            if((user_info->pq->fid != p_l2_node->fid) || (user_info->pq->gport != l2_info_sys.addr.l2_addr.gport))
            {
                ret = CTC_E_NONE;
                goto done;
            }
        }

        p_user_addr_buf = user_info->pr->buffer;
        if (user_info->p_detail)
        {
            mac_lookup_result_t rst;
            sal_memset(&rst, 0, sizeof(rst));
            CTC_ERROR_DUMP(_sys_usw_l2_acc_lookup_mac_fid(lchip, p_l2_node->mac, p_l2_node->fid, &rst));
            user_info->p_detail->key_index = rst.key_index;
            user_info->p_detail->ad_index = p_l2_node->adptr->index;
        }
        sal_memcpy(p_user_addr_buf , &l2_info_sys.addr.l2_addr, sizeof(ctc_l2_addr_t));
        sal_memcpy(p_user_addr_buf->mac , p_l2_node->mac, sizeof(mac_addr_t));
        p_user_addr_buf->fid = p_l2_node->fid;

        if (user_info->p_detail)
        {
            user_info->p_detail->pending = 0;
            user_info->p_detail->flag = p_user_addr_buf->flag;
        }

        (user_info->pq->count) ++;
        if (user_info->pr->buffer_len >= sizeof(ctc_l2_addr_t))
        {
            user_info->pr->buffer_len -= sizeof(ctc_l2_addr_t);
            user_info->pr->buffer ++;
            if (user_info->p_detail)
            {
                user_info->p_detail ++;
            }
        }
        else
        {
            /*user buf full*/
        }
    }

 done:
    if (bucket_node->next == NULL)
    {
        cur_hash_node_id +=  1;
        cur_list_id      =   0;
    }
    else
    {
        cur_hash_node_id += 0;
        cur_list_id      += 1;
    }
    FDB_MAC_FID_SW_QUERY_IDX_ENCODE(user_info->pr->next_query_index, cur_hash_node_id, cur_list_id);
    return ret;
}

int32
sys_usw_l2_hw_sync_add_db(uint8 lchip, ctc_l2_addr_t* l2_addr, uint32 nhid, uint32 index)
{
    SYS_L2_INIT_CHECK();
    if(pl2_usw_master[lchip]->sync_add_db)
    {
        pl2_usw_master[lchip]->sync_add_db(lchip, l2_addr, nhid, index);
    }
    return CTC_E_NONE;
}

int32
sys_usw_l2_hw_sync_remove_db(uint8 lchip, ctc_l2_addr_t* l2_addr)
{
    SYS_L2_INIT_CHECK();
    if(pl2_usw_master[lchip]->sync_remove_db)
    {
        pl2_usw_master[lchip]->sync_remove_db(lchip, l2_addr);
    }

    return CTC_E_NONE;
}

int32
sys_usw_l2_hw_sync_alloc_ad_idx(uint8 lchip, uint32* ad_index)
{
    return sys_usw_ftm_alloc_table_offset(lchip, DsMac_t, 1, 1, 1, ad_index);
}

int32
sys_usw_l2_hw_sync_free_ad_idx(uint8 lchip, uint32 ad_index)
{
    return sys_usw_ftm_free_table_offset(lchip, DsMac_t, 1, 1, ad_index);
}

int32
sys_usw_l2_update_station_move_action(uint8 lchip, uint32 ad_index, uint32 type)
{
    uint32 cmd = 0;
    uint32 field_val = 0;

    field_val = (type == CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD)?1:0;
    cmd = DRV_IOW(DsMac_t, DsMac_srcMismatchDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &field_val));

    field_val = (type == CTC_PORT_STATION_MOVE_ACTION_TYPE_DISCARD)?0:1;
    cmd = DRV_IOW(DsMac_t, DsMac_srcMismatchLearnEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, ad_index, cmd, &field_val));

    return CTC_E_NONE;
}
#endif
